From a14e181a76e41447a100813fc7af9fe5b6e68b8a Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Mon, 8 Jun 2020 15:04:26 -0500 Subject: Fold text better `fold_line` now has a lot of options that determine how to fold the text so that each line can be separately styled with ANSI escapes. It turns out that `less` only styles the first line of multi-line blocks that are ANSI-escaped, so this was necessary to make it look "good." --- bollux | 93 ++++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 28 deletions(-) diff --git a/bollux b/bollux index 919c370..96a372f 100755 --- a/bollux +++ b/bollux @@ -629,7 +629,7 @@ display() { # display METADATA [TITLE] { run iconv -f "${charset^^}" -t "UTF-8" | run tee "$BOLLUX_PAGESRC" | - run "$typeset" | + run "$typeset" | #cat run "${less_cmd[@]}" && bollux_quit } || run handle_keypress "$?" ;; @@ -729,6 +729,7 @@ typeset_gemini() { gemini_link() { local re="^(=>)[[:blank:]]*([^[:blank:]]+)[[:blank:]]*(.*)" local s t a l # sigil, text, annotation(url), line + local ln="$3" if ! ${2-false} && [[ "$1" =~ $re ]]; then s="${BASH_REMATCH[1]}" a="${BASH_REMATCH[2]}" @@ -739,11 +740,13 @@ gemini_link() { fi printf "\e[${C_SIGIL}m%${S_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" + printf "\e[${C_LINK_NUMBER}m[%d]${C_RESET} " "$ln" + fold_line -n -B "\e[${C_LINK_TITLE}m" -A "${C_RESET}" \ + -l "$((${#ln} + 3))" -m "${T_MARGIN}" \ + "$WIDTH" "$(trim_string "$t")" + fold_line -B " \e[${C_LINK_URL}m" -A "${C_RESET}" \ + -l "$((${#ln} + 3 + ${#t}))" -m "${T_MARGIN}" \ + "$WIDTH" "$a" else gemini_pre "$1" fi @@ -760,8 +763,8 @@ gemini_header() { hdrfmt="$(eval echo "\$C_HEADER$a")" printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" - printf -v l "\e[${hdrfmt}m%s${C_RESET}\n" "$t" - fold_line "$WIDTH" "$l" + fold_line -B "\e[${hdrfmt}m" -A "${C_RESET}" -m "${T_MARGIN}" \ + "$WIDTH" "$t" else gemini_pre "$1" fi @@ -775,8 +778,8 @@ gemini_list() { t="${BASH_REMATCH[2]}" printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" - printf -v l "\e[${C_LIST}m%s${C_RESET}\n" "$t" - fold_line "$WIDTH" "$l" + fold_line -B "\e[${C_LIST}m" -A "${C_RESET}" -m "$T_MARGIN" \ + "$WIDTH" "$t" else gemini_pre "$1" fi @@ -790,8 +793,8 @@ gemini_quote() { t="${BASH_REMATCH[2]}" printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" - printf -v l "\e[${C_QUOTE}m%s${C_RESET}\n" "$t" - fold_line "$WIDTH" "$l" + fold_line -B "\e[${C_QUOTE}m" -A "${C_RESET}" -m "$T_MARGIN" \ + "$WIDTH" "$t" else gemini_pre "$1" fi @@ -800,7 +803,8 @@ gemini_quote() { gemini_text() { if ! ${2-false}; then printf "%${S_MARGIN}s " ' ' - fold_line "$WIDTH" "$1" + fold_line -m "$T_MARGIN" \ + "$WIDTH" "$1" else gemini_pre "$1" fi @@ -812,32 +816,65 @@ gemini_pre() { } # wrap lines on words to WIDTH -fold_line() { # fold_line WIDTH TEXT - local width="$1" - local margin="${2%%[![:space:]]*}" - if [[ "$margin" ]]; then - margin="${#margin}" - else - margin="$T_MARGIN" +fold_line() { + # fold_line [-n] [-m MARGIN] [-f MARGIN] [-l LENGTH] [-B BEFORE] [-A AFTER] WIDTH TEXT + local newline=true + local -i margin_all=0 margin_first=0 width ll=0 wl=0 wn=0 + local before="" after="" + OPTIND=0 + while getopts nm:f:l:B:A: OPT; do + case "$OPT" in + n) # -n = no trailing newline + newline=false + ;; + m) # -m MARGIN = margin for all lines + margin_all="$OPTARG" + ;; + f) # -f MARGIN = margin for first line + margin_first="$OPTARG" + ;; + l) # -l LENGTH = length of line before starting fold + ll="$OPTARG" + ;; + B) # -B BEFORE = text to insert before each line + before="$OPTARG" + ;; + A) # -A AFTER = text to insert after each line + after="$OPTARG" + ;; + *) return 1 ;; + esac + done + shift "$((OPTIND - 1))" + width="$1" + ll=$((ll % width)) + #shellcheck disable=2086 + set -- $2 + + local plain="" + if ((margin_first > 0 && ll == 0)); then + printf "%${margin_first}s" " " + fi + if [[ -n "$before" ]]; then + printf '%b' "$before" fi - local ll=0 wl plain - # shellcheck disable=2086 - set -- $2 # TODO: is this the best way? - for word; do + ((wn += 1)) shopt -s extglob plain="${word//$'\x1b'\[*([0-9;])m/}" shopt -u extglob wl=$((${#plain} + 1)) if (((ll + wl) >= width)); then - printf "\n%${margin}s" ' ' + printf "${after:-}\n%${margin_all}s${before:-}" ' ' ll=$wl else - ll=$((ll + wl)) + ((ll += wl)) fi - printf '%s ' "$word" + printf '%s' "$word" + ((wn != $#)) && printf ' ' done - printf '\n' + [[ -n "$after" ]] && printf '%b' "$after" + $newline && printf '\n' } # use the exit code from less (see mklesskey) to do things -- cgit 1.4.1-21-gabe81