Archive
[bollux.git/.git] / typeset_gemini.sh
1 typeset_gemini() {
2         local pre=false
3         local ln=0
4
5         while read -r line; do
6                 case "$line" in
7                 '```')
8                         flip pre
9                         continue
10                         ;;
11                 =\>*)
12                         : $((ln += 1))
13                         gemini_link "$line" $pre
14                         ;;
15                 \#*) gemini_header "$line" $pre ;;
16                 \**) gemini_list "$line" $pre ;;
17                 *) gemini_text "$line" $pre ;;
18                 esac
19         done
20 }
21
22 gemini_link() {
23         local re="^(=>)[[:blank:]]*([^[:blank:]]+)[[:blank:]]*(.*)"
24         local s t a # sigil, text, annotation(url)
25         if ! ${2-false} && [[ "$1" =~ $re ]]; then
26                 s="${BASH_REMATCH[1]}"
27                 t="${BASH_REMATCH[3]}"
28                 a="${BASH_REMATCH[2]}"
29
30                 printf "$C_SIGIL%-${MARGIN}s" "$s"
31                 fold_line "$WIDTH" "$(printf "$C_LINK_TITLE%s $C_LINK_URL%s$C_RESET\n" \
32                         "$t" "$a")"
33         else
34                 gemini_pre "$1"
35         fi
36 }
37
38 gemini_header() {
39         local re="^(#+)[[:blank:]]*(.*)"
40         local s t a # sigil, text, annotation(lvl)
41         if ! ${2-false} && [[ "$1" =~ $re ]]; then
42                 s="${BASH_REMATCH[1]}"
43                 a="${#BASH_REMATCH[1]}"
44                 t="${BASH_REMATCH[2]}"
45
46                 local hdrfmt
47                 hdrfmt="$(eval echo "\$C_HEADER$a")"
48                 printf "$C_SIGIL%-${MARGIN}s$hdrfmt%s$C_RESET\n" \
49                         "$s" "$(fold_line "$WIDTH" "$t")"
50         else
51                 gemini_pre "$1"
52         fi
53 }
54
55 gemini_list() {
56         local re="^(\*)[[:blank:]]*(.*)"
57         local s t a # sigil, text, annotation(n/a)
58         if ! ${2-false} && [[ "$1" =~ $re ]]; then
59                 s="${BASH_REMATCH[1]}"
60                 t="${BASH_REMATCH[2]}"
61
62                 printf "$C_SIGIL%-${MARGIN}s$C_LIST%s$C_RESET\n" \
63                         "$s" "$(fold_line "$WIDTH" "$t")"
64         else
65                 gemini_pre "$1"
66         fi
67 }
68
69 gemini_text() {
70         printf "%${MARGIN}s" ' '
71         if ! ${2-false}; then
72                 fold_line "$WIDTH" "$1"
73         else
74                 gemini_pre "$1"
75         fi
76 }
77
78 gemini_pre() {
79         printf "%${MARGIN}s%s" ' ' "$1"
80 }
81
82 flip() { # flip NAME
83         [[ "${!1}" == true || "${!1}" == false ]] || return 1
84
85         if "${!1}"; then
86                 eval "$1=false"
87         else
88                 eval "$1=true"
89         fi
90 }
91
92 fold_line() { # fold_line WIDTH TEXT
93         local width="$1"
94         local ll=0 wl plain
95         # shellcheck disable=2086
96         # TODO: determine if this is the best way to do it
97         set -- $2
98
99         for word; do
100                 plain="${word//$'\x1b'\[*([0-9;])m/}"
101                 wl=$((${#plain} + 1))
102                 if (((ll + wl) >= width)); then
103                         printf "\n%${MARGIN}s" ' '
104                         ll=$wl
105                 else
106                         ll=$((ll + wl))
107                 fi
108                 printf '%s ' "$word"
109         done
110         printf '\n'
111 }
112
113 # just here for reference
114 strip() { # strip control sequences
115         # https://stackoverflow.com/a/55872518
116         shopt -s extglob
117         while IFS='' read -r x; do
118                 # remove colors
119                 echo "${x//$'\x1b'\[*([0-9;])m/}"
120         done
121 }
122
123 test() {
124         MARGIN=4
125         WIDTH=60
126         #shopt -s checkwinsize; (:;:)
127         #WIDTH="$((COLUMNS - (MARGIN*2)))"
128         C_LINK_TITLE=$'\e[34m'
129         C_LINK_URL=$'\e[31m'
130         C_RESET=$'\e[0m'
131         typeset_gemini <<-'EOF'
132                 # Project Gemini
133                 
134                 ## Overview
135                 
136                 Gemini is a new internet protocol which:
137                 
138                 * Is heavier than gopher
139                 * Is lighter than the web
140                 * Will not replace either
141                 * Strives for maximum power to weight ratio
142                 * Takes user privacy very seriously
143                 
144                 ## Resources
145                 
146                 => docs/        Gemini documentation
147                 => software/    Gemini software
148                 => servers/     Known Gemini servers
149                 => https://lists.orbitalfox.eu/listinfo/gemini  Gemini mailing list
150                 => gemini://gemini.conman.org/test/torture/     Gemini client torture test
151                 
152                 ## Web proxies
153                 
154                 => https://portal.mozz.us/?url=gemini%3A%2F%2Fgemini.circumlunar.space%2F&fmt=fixed     Gemini-to-web proxy service
155                 => https://proxy.vulpes.one/gemini/gemini.circumlunar.space     Another Gemini-to-web proxy service
156                 
157                 ## Search engines
158                 
159                 => gemini://gus.guru/   Gemini Universal Search engine
160                 => gemini://houston.coder.town  Houston search engine
161                 
162                 ## Geminispace aggregators (experimental!)
163                 
164                 => capcom/      CAPCOM
165                 => gemini://rawtext.club:1965/~sloum/spacewalk.gmi      Spacewalk
166                 
167                 ## Free Gemini hosting
168                 
169                 => users/       Users with Gemini content on this server
170         EOF
171 }
172 test