diff options
author | Case Duckworth | 2020-06-08 15:04:26 -0500 |
---|---|---|
committer | Case Duckworth | 2020-06-08 15:04:26 -0500 |
commit | a14e181a76e41447a100813fc7af9fe5b6e68b8a (patch) | |
tree | f036c96587eb865382af58c03faf1d2d47f005e2 | |
parent | Enable extglob on extglob (diff) | |
download | bollux-a14e181a76e41447a100813fc7af9fe5b6e68b8a.tar.gz bollux-a14e181a76e41447a100813fc7af9fe5b6e68b8a.zip |
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."
-rwxr-xr-x | bollux | 93 |
1 files 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] | |||
629 | { | 629 | { |
630 | run iconv -f "${charset^^}" -t "UTF-8" | | 630 | run iconv -f "${charset^^}" -t "UTF-8" | |
631 | run tee "$BOLLUX_PAGESRC" | | 631 | run tee "$BOLLUX_PAGESRC" | |
632 | run "$typeset" | | 632 | run "$typeset" | #cat |
633 | run "${less_cmd[@]}" && bollux_quit | 633 | run "${less_cmd[@]}" && bollux_quit |
634 | } || run handle_keypress "$?" | 634 | } || run handle_keypress "$?" |
635 | ;; | 635 | ;; |
@@ -729,6 +729,7 @@ typeset_gemini() { | |||
729 | gemini_link() { | 729 | gemini_link() { |
730 | local re="^(=>)[[:blank:]]*([^[:blank:]]+)[[:blank:]]*(.*)" | 730 | local re="^(=>)[[:blank:]]*([^[:blank:]]+)[[:blank:]]*(.*)" |
731 | local s t a l # sigil, text, annotation(url), line | 731 | local s t a l # sigil, text, annotation(url), line |
732 | local ln="$3" | ||
732 | if ! ${2-false} && [[ "$1" =~ $re ]]; then | 733 | if ! ${2-false} && [[ "$1" =~ $re ]]; then |
733 | s="${BASH_REMATCH[1]}" | 734 | s="${BASH_REMATCH[1]}" |
734 | a="${BASH_REMATCH[2]}" | 735 | a="${BASH_REMATCH[2]}" |
@@ -739,11 +740,13 @@ gemini_link() { | |||
739 | fi | 740 | fi |
740 | 741 | ||
741 | printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" | 742 | printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" |
742 | printf -v l "\e[${C_LINK_NUMBER}m[%d]${C_RESET} \ | 743 | printf "\e[${C_LINK_NUMBER}m[%d]${C_RESET} " "$ln" |
743 | \e[${C_LINK_TITLE}m%s${C_RESET} \ | 744 | fold_line -n -B "\e[${C_LINK_TITLE}m" -A "${C_RESET}" \ |
744 | \e[${C_LINK_URL}m%s${C_RESET}\n" \ | 745 | -l "$((${#ln} + 3))" -m "${T_MARGIN}" \ |
745 | "$3" "$t" "$a" | 746 | "$WIDTH" "$(trim_string "$t")" |
746 | fold_line "$WIDTH" "$l" | 747 | fold_line -B " \e[${C_LINK_URL}m" -A "${C_RESET}" \ |
748 | -l "$((${#ln} + 3 + ${#t}))" -m "${T_MARGIN}" \ | ||
749 | "$WIDTH" "$a" | ||
747 | else | 750 | else |
748 | gemini_pre "$1" | 751 | gemini_pre "$1" |
749 | fi | 752 | fi |
@@ -760,8 +763,8 @@ gemini_header() { | |||
760 | hdrfmt="$(eval echo "\$C_HEADER$a")" | 763 | hdrfmt="$(eval echo "\$C_HEADER$a")" |
761 | 764 | ||
762 | printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" | 765 | printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" |
763 | printf -v l "\e[${hdrfmt}m%s${C_RESET}\n" "$t" | 766 | fold_line -B "\e[${hdrfmt}m" -A "${C_RESET}" -m "${T_MARGIN}" \ |
764 | fold_line "$WIDTH" "$l" | 767 | "$WIDTH" "$t" |
765 | else | 768 | else |
766 | gemini_pre "$1" | 769 | gemini_pre "$1" |
767 | fi | 770 | fi |
@@ -775,8 +778,8 @@ gemini_list() { | |||
775 | t="${BASH_REMATCH[2]}" | 778 | t="${BASH_REMATCH[2]}" |
776 | 779 | ||
777 | printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" | 780 | printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" |
778 | printf -v l "\e[${C_LIST}m%s${C_RESET}\n" "$t" | 781 | fold_line -B "\e[${C_LIST}m" -A "${C_RESET}" -m "$T_MARGIN" \ |
779 | fold_line "$WIDTH" "$l" | 782 | "$WIDTH" "$t" |
780 | else | 783 | else |
781 | gemini_pre "$1" | 784 | gemini_pre "$1" |
782 | fi | 785 | fi |
@@ -790,8 +793,8 @@ gemini_quote() { | |||
790 | t="${BASH_REMATCH[2]}" | 793 | t="${BASH_REMATCH[2]}" |
791 | 794 | ||
792 | printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" | 795 | printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s" |
793 | printf -v l "\e[${C_QUOTE}m%s${C_RESET}\n" "$t" | 796 | fold_line -B "\e[${C_QUOTE}m" -A "${C_RESET}" -m "$T_MARGIN" \ |
794 | fold_line "$WIDTH" "$l" | 797 | "$WIDTH" "$t" |
795 | else | 798 | else |
796 | gemini_pre "$1" | 799 | gemini_pre "$1" |
797 | fi | 800 | fi |
@@ -800,7 +803,8 @@ gemini_quote() { | |||
800 | gemini_text() { | 803 | gemini_text() { |
801 | if ! ${2-false}; then | 804 | if ! ${2-false}; then |
802 | printf "%${S_MARGIN}s " ' ' | 805 | printf "%${S_MARGIN}s " ' ' |
803 | fold_line "$WIDTH" "$1" | 806 | fold_line -m "$T_MARGIN" \ |
807 | "$WIDTH" "$1" | ||
804 | else | 808 | else |
805 | gemini_pre "$1" | 809 | gemini_pre "$1" |
806 | fi | 810 | fi |
@@ -812,32 +816,65 @@ gemini_pre() { | |||
812 | } | 816 | } |
813 | 817 | ||
814 | # wrap lines on words to WIDTH | 818 | # wrap lines on words to WIDTH |
815 | fold_line() { # fold_line WIDTH TEXT | 819 | fold_line() { |
816 | local width="$1" | 820 | # fold_line [-n] [-m MARGIN] [-f MARGIN] [-l LENGTH] [-B BEFORE] [-A AFTER] WIDTH TEXT |
817 | local margin="${2%%[![:space:]]*}" | 821 | local newline=true |
818 | if [[ "$margin" ]]; then | 822 | local -i margin_all=0 margin_first=0 width ll=0 wl=0 wn=0 |
819 | margin="${#margin}" | 823 | local before="" after="" |
820 | else | 824 | OPTIND=0 |
821 | margin="$T_MARGIN" | 825 | while getopts nm:f:l:B:A: OPT; do |
826 | case "$OPT" in | ||
827 | n) # -n = no trailing newline | ||
828 | newline=false | ||
829 | ;; | ||
830 | m) # -m MARGIN = margin for all lines | ||
831 | margin_all="$OPTARG" | ||
832 | ;; | ||
833 | f) # -f MARGIN = margin for first line | ||
834 | margin_first="$OPTARG" | ||
835 | ;; | ||
836 | l) # -l LENGTH = length of line before starting fold | ||
837 | ll="$OPTARG" | ||
838 | ;; | ||
839 | B) # -B BEFORE = text to insert before each line | ||
840 | before="$OPTARG" | ||
841 | ;; | ||
842 | A) # -A AFTER = text to insert after each line | ||
843 | after="$OPTARG" | ||
844 | ;; | ||
845 | *) return 1 ;; | ||
846 | esac | ||
847 | done | ||
848 | shift "$((OPTIND - 1))" | ||
849 | width="$1" | ||
850 | ll=$((ll % width)) | ||
851 | #shellcheck disable=2086 | ||
852 | set -- $2 | ||
853 | |||
854 | local plain="" | ||
855 | if ((margin_first > 0 && ll == 0)); then | ||
856 | printf "%${margin_first}s" " " | ||
857 | fi | ||
858 | if [[ -n "$before" ]]; then | ||
859 | printf '%b' "$before" | ||
822 | fi | 860 | fi |
823 | local ll=0 wl plain | ||
824 | # shellcheck disable=2086 | ||
825 | set -- $2 # TODO: is this the best way? | ||
826 | |||
827 | for word; do | 861 | for word; do |
862 | ((wn += 1)) | ||
828 | shopt -s extglob | 863 | shopt -s extglob |
829 | plain="${word//$'\x1b'\[*([0-9;])m/}" | 864 | plain="${word//$'\x1b'\[*([0-9;])m/}" |
830 | shopt -u extglob | 865 | shopt -u extglob |
831 | wl=$((${#plain} + 1)) | 866 | wl=$((${#plain} + 1)) |
832 | if (((ll + wl) >= width)); then | 867 | if (((ll + wl) >= width)); then |
833 | printf "\n%${margin}s" ' ' | 868 | printf "${after:-}\n%${margin_all}s${before:-}" ' ' |
834 | ll=$wl | 869 | ll=$wl |
835 | else | 870 | else |
836 | ll=$((ll + wl)) | 871 | ((ll += wl)) |
837 | fi | 872 | fi |
838 | printf '%s ' "$word" | 873 | printf '%s' "$word" |
874 | ((wn != $#)) && printf ' ' | ||
839 | done | 875 | done |
840 | printf '\n' | 876 | [[ -n "$after" ]] && printf '%b' "$after" |
877 | $newline && printf '\n' | ||
841 | } | 878 | } |
842 | 879 | ||
843 | # use the exit code from less (see mklesskey) to do things | 880 | # use the exit code from less (see mklesskey) to do things |