diff options
author | Case Duckworth | 2021-03-02 12:57:38 -0600 |
---|---|---|
committer | Case Duckworth | 2021-03-02 12:58:27 -0600 |
commit | afb216344735397615466174b8ca184691ea66f8 (patch) | |
tree | 6bc842838a9715522d8c49b19505d43515db0fdb | |
parent | Bump version (diff) | |
download | bollux-afb216344735397615466174b8ca184691ea66f8.tar.gz bollux-afb216344735397615466174b8ca184691ea66f8.zip |
Add commentary
-rw-r--r-- | bollux | 229 |
1 files changed, 178 insertions, 51 deletions
diff --git a/bollux b/bollux index 26dc316..a7c5f93 100644 --- a/bollux +++ b/bollux | |||
@@ -3,11 +3,45 @@ | |||
3 | # Author: Case Duckworth | 3 | # Author: Case Duckworth |
4 | # License: MIT | 4 | # License: MIT |
5 | # Version: 0.4.0 | 5 | # Version: 0.4.0 |
6 | # | ||
7 | # Commentary: | ||
8 | # | ||
9 | # The impetus for this program came from a Mastodon conversation I had where | ||
10 | # someone mentioned the "simplest possible Gemini client" was this: | ||
11 | # | ||
12 | # openssl s_client -gin_foe -quiet -connect $server:1965 <<< "$url" | ||
13 | # | ||
14 | # That's still at the heart of this program (see `gemini_request'): `bollux' is | ||
15 | # basically a half-functioning convenience wrapper around that openssl call. | ||
16 | # The first versions of `bollux' used `gawk' and a lot of other tools on top of | ||
17 | # bash, but after reading Dylan Araps' Pure Bash Bible[1] and other works, I | ||
18 | # decided to make as much of it in Bash as possible. Thus, currently `bollux' | ||
19 | # requires `bash' v. 4+, `less' (a recent, non-busybox version), `dd' for | ||
20 | # downloads, `openssl' for requests, and `iconv' to convert pages to UTF-8. | ||
21 | # Future versions will hopefully have a pager fully implemented in bash, so that | ||
22 | # I won't have to worry about less's weird incompatibilities and keybinding | ||
23 | # things. That's a major project though, and I'm scared. | ||
24 | # | ||
25 | # The following works were referenced when writing this, and I've tried to | ||
26 | # credit them in comments below. Following each link, I'll include a "short | ||
27 | # code" that I'll use to reference them in those comments, if necessary to keep | ||
28 | # them shorter than 80 characters. | ||
29 | # | ||
30 | # [1]: https://github.com/dylanaraps/pure-bash-bible [PBB] | ||
31 | # [2]: https://tools.ietf.org/html/rfc3986 [URLspec] | ||
32 | # [3]: https://gemini.circumlunar.space/docs/specification.html [GEMspec] | ||
33 | # [4]: https://tools.ietf.org/html/rfc1436 [GOPHERprotocol] | ||
34 | # [5]: https://tools.ietf.org/html/rfc4266 [GOPHERurl] | ||
35 | # [6]: [GOPHER_GEMINI]: | ||
36 | # https://github.com/jamestomasino/dotfiles-minimal/blob/master/bin/gophermap2gemini.awk | ||
37 | # | ||
38 | # Code: | ||
6 | 39 | ||
7 | # Program information | 40 | # Program information |
8 | PRGN="${0##*/}" # Easiest way to get the script name | 41 | PRGN="${0##*/}" # Easiest way to get the script name |
9 | VRSN=0.4.1 # I /try/ to follow semver? IDK. | 42 | VRSN=0.4.1 # I /try/ to follow semver? IDK. |
10 | 43 | ||
44 | # Print a useful help message (`bollux -h'). | ||
11 | bollux_usage() { | 45 | bollux_usage() { |
12 | cat <<END | 46 | cat <<END |
13 | $PRGN (v. $VRSN): a bash gemini client | 47 | $PRGN (v. $VRSN): a bash gemini client |
@@ -24,12 +58,19 @@ parameters: | |||
24 | END | 58 | END |
25 | } | 59 | } |
26 | 60 | ||
61 | # UTILITY FUNCTIONS ############################################################ | ||
62 | |||
63 | # Run a command, but log it first. | ||
64 | # | ||
65 | # See `log' for the available levels. | ||
27 | run() { # run COMMAND... | 66 | run() { # run COMMAND... |
67 | # I have to add a `trap' here for SIGINT (C-c) to work properly. | ||
28 | trap bollux_quit SIGINT | 68 | trap bollux_quit SIGINT |
29 | log debug "$*" | 69 | log debug "$*" |
30 | "$@" | 70 | "$@" |
31 | } | 71 | } |
32 | 72 | ||
73 | # Exit with an error and a message describing it. | ||
33 | die() { # die EXIT_CODE MESSAGE | 74 | die() { # die EXIT_CODE MESSAGE |
34 | local ec="$1" | 75 | local ec="$1" |
35 | shift | 76 | shift |
@@ -37,20 +78,35 @@ die() { # die EXIT_CODE MESSAGE | |||
37 | exit "$ec" | 78 | exit "$ec" |
38 | } | 79 | } |
39 | 80 | ||
40 | # builtin replacement for `sleep` | 81 | # Exit with success, printing a fun message. |
41 | # https://github.com/dylanaraps/pure-bash-bible#use-read-as-an-alternative-to-the-sleep-command | 82 | # |
83 | # The default message is from the wonderful show "Cowboy Bebop." | ||
84 | bollux_quit() { | ||
85 | printf '\e[1m%s\e[0m:\t\e[3m%s\e[0m\n' "$PRGN" "$BOLLUX_BYEMSG" | ||
86 | exit | ||
87 | } | ||
88 | # SIGINT is C-c, and I want to make sure bollux quits when it's typed. | ||
89 | trap bollux_quit SIGINT | ||
90 | |||
91 | # Bash built-in replacement for `sleep` | ||
92 | # | ||
93 | # PBB: #use-read-as-an-alternative-to-the-sleep-command | ||
42 | sleep() { # sleep SECONDS | 94 | sleep() { # sleep SECONDS |
43 | read -rt "$1" <> <(:) || : | 95 | read -rt "$1" <> <(:) || : |
44 | } | 96 | } |
45 | 97 | ||
46 | # https://github.com/dylanaraps/pure-bash-bible/ | 98 | # Trim leading and trailing whitespace from a string. |
99 | # | ||
100 | # PBB: #trim-leading-and-trailing-white-space-from-string | ||
47 | trim_string() { # trim_string STRING | 101 | trim_string() { # trim_string STRING |
48 | : "${1#"${1%%[![:space:]]*}"}" | 102 | : "${1#"${1%%[![:space:]]*}"}" |
49 | : "${_%"${_##*[![:space:]]}"}" | 103 | : "${_%"${_##*[![:space:]]}"}" |
50 | printf '%s\n' "$_" | 104 | printf '%s\n' "$_" |
51 | } | 105 | } |
52 | 106 | ||
53 | # cycle a variable, e.g. from 'one,two,three' => 'two,three,one' | 107 | # Cycle a variable. |
108 | # | ||
109 | # e.g. 'cycle_list one,two,three' => 'two,three,one' | ||
54 | cycle_list() { # cycle_list LIST DELIM | 110 | cycle_list() { # cycle_list LIST DELIM |
55 | local list="${!1}" delim="$2" | 111 | local list="${!1}" delim="$2" |
56 | local first="${list%%${delim}*}" | 112 | local first="${list%%${delim}*}" |
@@ -58,12 +114,17 @@ cycle_list() { # cycle_list LIST DELIM | |||
58 | printf -v "$1" '%s%s%s' "${rest}" "${delim}" "${first}" | 114 | printf -v "$1" '%s%s%s' "${rest}" "${delim}" "${first}" |
59 | } | 115 | } |
60 | 116 | ||
61 | # determine the first element of a list, e.g. 'one,two,three' => 'one' | 117 | # Determine the first element of a delimited list. |
118 | # | ||
119 | # e.g. 'first one,two,three' => 'one' | ||
62 | first() { # first LIST DELIM | 120 | first() { # first LIST DELIM |
63 | local list="${!1}" delim="$2" | 121 | local list="${!1}" delim="$2" |
64 | printf '%s\n' "${list%%${delim}*}" | 122 | printf '%s\n' "${list%%${delim}*}" |
65 | } | 123 | } |
66 | 124 | ||
125 | # Log a message to stderr (&2). | ||
126 | # | ||
127 | # TODO: document | ||
67 | log() { # log LEVEL MESSAGE | 128 | log() { # log LEVEL MESSAGE |
68 | [[ "$BOLLUX_LOGLEVEL" == QUIET ]] && return | 129 | [[ "$BOLLUX_LOGLEVEL" == QUIET ]] && return |
69 | local fmt | 130 | local fmt |
@@ -83,22 +144,49 @@ log() { # log LEVEL MESSAGE | |||
83 | printf >&2 '\e[%sm%s:%s:\e[0m\t%s\n' "$fmt" "$PRGN" "${FUNCNAME[1]}" "$*" | 144 | printf >&2 '\e[%sm%s:%s:\e[0m\t%s\n' "$fmt" "$PRGN" "${FUNCNAME[1]}" "$*" |
84 | } | 145 | } |
85 | 146 | ||
86 | # main entry point | 147 | # Set the terminal title. |
148 | set_title() { # set_title STRING | ||
149 | printf '\e]2;%s\007' "$*" | ||
150 | } | ||
151 | |||
152 | # Prompt the user for input. | ||
153 | # | ||
154 | # This is a thin wrapper around `read', a bash built-in. Because of the | ||
155 | # way bollux messes around with stein and stdout, I need to read directly from | ||
156 | # the TTY with this function. | ||
157 | prompt() { # prompt [-u] PROMPT [READ_ARGS...] | ||
158 | local read_cmd=(read -e -r) | ||
159 | if [[ "$1" == "-u" ]]; then | ||
160 | read_cmd+=(-i "$BOLLUX_URL") | ||
161 | shift | ||
162 | fi | ||
163 | local prompt="$1" | ||
164 | shift | ||
165 | read_cmd+=(-p "$prompt> ") | ||
166 | "${read_cmd[@]}" </dev/tty "$@" | ||
167 | } | ||
168 | |||
169 | # MAIN BOLLUX DISPATCH FUNCTIONS ############################################### | ||
170 | |||
171 | # Main entry point into `bollux'. | ||
172 | # | ||
173 | # See the `if' block at the bottom of this script. | ||
87 | bollux() { | 174 | bollux() { |
88 | run bollux_config # TODO: figure out better config method | 175 | run bollux_config # TODO: figure out better config method |
89 | run bollux_args "$@" # and argument parsing | 176 | run bollux_args "$@" # and argument parsing |
90 | run bollux_init | 177 | run bollux_init |
91 | 178 | ||
179 | # If the user hasn't configured a home page, $BOLLUX_URL will be blank. | ||
180 | # So, prompt the user where to go. | ||
92 | if [[ ! "${BOLLUX_URL:+x}" ]]; then | 181 | if [[ ! "${BOLLUX_URL:+x}" ]]; then |
93 | run prompt GO BOLLUX_URL | 182 | run prompt GO BOLLUX_URL |
94 | fi | 183 | fi |
95 | |||
96 | log d "BOLLUX_URL='$BOLLUX_URL'" | 184 | log d "BOLLUX_URL='$BOLLUX_URL'" |
97 | 185 | ||
98 | run blastoff -u "$BOLLUX_URL" | 186 | run blastoff -u "$BOLLUX_URL" # Visit the specified URL. |
99 | } | 187 | } |
100 | 188 | ||
101 | # process command-line arguments | 189 | # Process command-line arguments. |
102 | bollux_args() { | 190 | bollux_args() { |
103 | while getopts :hvq OPT; do | 191 | while getopts :hvq OPT; do |
104 | case "$OPT" in | 192 | case "$OPT" in |
@@ -113,14 +201,26 @@ bollux_args() { | |||
113 | esac | 201 | esac |
114 | done | 202 | done |
115 | shift $((OPTIND - 1)) | 203 | shift $((OPTIND - 1)) |
204 | |||
205 | # If there's a leftover argument, it's the URL to visit. | ||
116 | if (($# == 1)); then | 206 | if (($# == 1)); then |
117 | BOLLUX_URL="$1" | 207 | BOLLUX_URL="$1" |
118 | fi | 208 | fi |
119 | } | 209 | } |
120 | 210 | ||
121 | # process config file and set variables | 211 | # Source the configuration file and set remaining variables. |
212 | # | ||
213 | # Since `bollux_config' is loaded before `bollux_args', there's no way to | ||
214 | # specify a configuration file from the command line. I run `bollux_args' | ||
215 | # second so that command-line options (mostly $BOLLUX_URL) can supersede | ||
216 | # config-file options, and I'm not sure how to rectify the situation. | ||
217 | # | ||
218 | # Anyway, the config file `bollux.conf' is just a bash file that's sourced in | ||
219 | # this function. After that, I use a little bash trick to set all the remaining | ||
220 | # variables to default values with `: "${VAR:=value}"'. | ||
122 | bollux_config() { | 221 | bollux_config() { |
123 | : "${BOLLUX_CONFIG:=${XDG_CONFIG_HOME:-$HOME/.config}/bollux/bollux.conf}" | 222 | : "${BOLLUX_CONF_DIR:=${XDG_CONFIG_HOME:-$HOME/.config}/bollux}" |
223 | : "${BOLLUX_CONFIG:=$BOLLUX_CONF_DIR/bollux.conf}" | ||
124 | 224 | ||
125 | if [ -f "$BOLLUX_CONFIG" ]; then | 225 | if [ -f "$BOLLUX_CONFIG" ]; then |
126 | log debug "Loading config file '$BOLLUX_CONFIG'" | 226 | log debug "Loading config file '$BOLLUX_CONFIG'" |
@@ -145,7 +245,7 @@ bollux_config() { | |||
145 | : "${KEY_FORWARD:=']'}" # go forward in the history | 245 | : "${KEY_FORWARD:=']'}" # go forward in the history |
146 | : "${KEY_REFRESH:=r}" # refresh the page | 246 | : "${KEY_REFRESH:=r}" # refresh the page |
147 | : "${KEY_CYCLE_PRE:=p}" # cycle T_PRE_DISPLAY | 247 | : "${KEY_CYCLE_PRE:=p}" # cycle T_PRE_DISPLAY |
148 | : "${BOLLUX_CUSTOM_LESSKEY:=${XDG_CONFIG_HOME:-$HOME/.config}/bollux/bollux.lesskey}" | 248 | : "${BOLLUX_CUSTOM_LESSKEY:=$BOLLUX_CONF_DIR/bollux.lesskey}" |
149 | ## files | 249 | ## files |
150 | : "${BOLLUX_DATADIR:=${XDG_DATA_HOME:-$HOME/.local/share}/bollux}" | 250 | : "${BOLLUX_DATADIR:=${XDG_DATA_HOME:-$HOME/.local/share}/bollux}" |
151 | : "${BOLLUX_DOWNDIR:=.}" # where to save downloads | 251 | : "${BOLLUX_DOWNDIR:=.}" # where to save downloads |
@@ -154,7 +254,8 @@ bollux_config() { | |||
154 | BOLLUX_HISTFILE="$BOLLUX_DATADIR/history" # where to save history | 254 | BOLLUX_HISTFILE="$BOLLUX_DATADIR/history" # where to save history |
155 | ## typesetting | 255 | ## typesetting |
156 | : "${T_MARGIN:=4}" # left and right margin | 256 | : "${T_MARGIN:=4}" # left and right margin |
157 | : "${T_WIDTH:=0}" # width of the viewport -- 0 = get term width | 257 | : "${T_WIDTH:=0}" # width of the view port |
258 | # 0 = get term width | ||
158 | : "${T_PRE_DISPLAY:=both,pre,alt}" # how to view PRE blocks | 259 | : "${T_PRE_DISPLAY:=both,pre,alt}" # how to view PRE blocks |
159 | # colors -- these will be wrapped in \e[ __ m | 260 | # colors -- these will be wrapped in \e[ __ m |
160 | C_RESET='\e[0m' # reset | 261 | C_RESET='\e[0m' # reset |
@@ -169,59 +270,63 @@ bollux_config() { | |||
169 | : "${C_QUOTE:=3}" # quote formatting | 270 | : "${C_QUOTE:=3}" # quote formatting |
170 | : "${C_PRE:=0}" # preformatted text formatting | 271 | : "${C_PRE:=0}" # preformatted text formatting |
171 | ## state | 272 | ## state |
172 | UC_BLANK=':?:' | 273 | UC_BLANK=':?:' # internal use only, should be non-URL chars |
173 | } | 274 | } |
174 | 275 | ||
175 | # quit happily | ||
176 | bollux_quit() { | ||
177 | printf '\e[1m%s\e[0m:\t\e[3m%s\e[0m\n' "$PRGN" "$BOLLUX_BYEMSG" | ||
178 | exit | ||
179 | } | ||
180 | # trap C-c | ||
181 | trap bollux_quit SIGINT | ||
182 | 276 | ||
183 | # set the terminal title | 277 | # Load a URL. |
184 | set_title() { # set_title STRING | 278 | # |
185 | printf '\e]2;%s\007' "$*" | 279 | # I was feeling fancy when I named this function -- a more descriptive name |
186 | } | 280 | # would be 'bollux_goto' or something. |
187 | |||
188 | # prompt for input | ||
189 | prompt() { # prompt [-u] PROMPT [READ_ARGS...] | ||
190 | local read_cmd=(read -e -r) | ||
191 | if [[ "$1" == "-u" ]]; then | ||
192 | read_cmd+=(-i "$BOLLUX_URL") | ||
193 | shift | ||
194 | fi | ||
195 | local prompt="$1" | ||
196 | shift | ||
197 | read_cmd+=(-p "$prompt> ") | ||
198 | "${read_cmd[@]}" </dev/tty "$@" | ||
199 | } | ||
200 | |||
201 | # load a URL | ||
202 | blastoff() { # blastoff [-u] URL | 281 | blastoff() { # blastoff [-u] URL |
203 | local u | 282 | local u |
204 | 283 | ||
284 | # `blastoff' assumes a "well-formed" URL by default -- i.e., a URL with | ||
285 | # a protocol string and no extraneous whitespace. Since bollux can't | ||
286 | # trust the user to input a proper URL at a prompt, nor capsule authors | ||
287 | # to fully-form their URLs, so the -u flag is necessary for those | ||
288 | # use-cases. Otherwise, bollux knows the URL is well-formed -- or | ||
289 | # should be, due to the Gemini specification. | ||
205 | if [[ "$1" == "-u" ]]; then | 290 | if [[ "$1" == "-u" ]]; then |
206 | u="$(run uwellform "$2")" | 291 | u="$(run uwellform "$2")" |
207 | else | 292 | else |
208 | u="$1" | 293 | u="$1" |
209 | fi | 294 | fi |
210 | 295 | ||
296 | # After ensuring the URL is well-formed, `blastoff' needs to transform | ||
297 | # it according to the transform rules of RFC 3986 (see ยง5.2.2), which | ||
298 | # turns relative references into absolute references that bollux can use | ||
299 | # in its request to the server. That's followed by a check that the | ||
300 | # protocol is set, defaulting to Gemini if it isn't. | ||
301 | # | ||
302 | # Implementation detail: because Bash is really stupid when it comes to | ||
303 | # arrays, the URL functions u* (see below) work with an array defined | ||
304 | # with `local -a' and passed by name, not by value. Thus, the | ||
305 | # `urltransform url ...' instead of `urltransform "${url[@]}"' or | ||
306 | # similar. In addition, the `ucdef' and `ucset' functions take the name | ||
307 | # of the array element as parameters, not the element itself. | ||
211 | local -a url | 308 | local -a url |
212 | run utransform url "$BOLLUX_URL" "$u" | 309 | run utransform url "$BOLLUX_URL" "$u" |
213 | if ! ucdef url[1]; then | 310 | if ! ucdef url[1]; then |
214 | run ucset url[1] "$BOLLUX_PROTO" | 311 | run ucset url[1] "$BOLLUX_PROTO" |
215 | fi | 312 | fi |
216 | 313 | ||
314 | # To try and keep `bollux' as extensible as possible, I've written it | ||
315 | # only to expect two functions for every protocol it supports: | ||
316 | # `x_request' and `x_response', where `x' is the name of the protocol | ||
317 | # (the first element of the built `url' array). `declare -F' looks only | ||
318 | # for functions in the current scope, failing if it doesn't exist. | ||
319 | # | ||
320 | # In between `x_request' and `x_response', `blastoff' normalizes the | ||
321 | # line endings to UNIX-style (LF) for ease of display. | ||
217 | { | 322 | { |
218 | if declare -Fp "${url[1]}_request" >/dev/null 2>&1; then | 323 | if declare -F "${url[1]}_request" >/dev/null 2>&1; then |
219 | run "${url[1]}_request" "$url" | 324 | run "${url[1]}_request" "$url" |
220 | else | 325 | else |
221 | die 99 "No request handler for '${url[1]}'" | 326 | die 99 "No request handler for '${url[1]}'" |
222 | fi | 327 | fi |
223 | } | run normalize | { | 328 | } | run normalize | { |
224 | if declare -Fp "${url[1]}_response" >/dev/null 2>&1; then | 329 | if declare -F "${url[1]}_response" >/dev/null 2>&1; then |
225 | run "${url[1]}_response" "$url" | 330 | run "${url[1]}_response" "$url" |
226 | else | 331 | else |
227 | log d \ | 332 | log d \ |
@@ -232,8 +337,23 @@ blastoff() { # blastoff [-u] URL | |||
232 | } | 337 | } |
233 | } | 338 | } |
234 | 339 | ||
235 | # URLS | 340 | # URLS: https://tools.ietf.org/html/rfc3986 #################################### |
236 | ## https://tools.ietf.org/html/rfc3986 | 341 | # |
342 | # Most of these functions are Bash implementations of functionality laid out in | ||
343 | # the linked RFC specification. I'll refer to the section numbers above each | ||
344 | # function. | ||
345 | # | ||
346 | # In addition, most of these functions take arrays or array elements passed /by | ||
347 | # name/, instead of /value/ -- i.e., instead of calling `usplit $url', call | ||
348 | # `usplit url'. Passing values by name is necessary because of Bash's weird | ||
349 | # array handling. | ||
350 | # | ||
351 | ################################################################################ | ||
352 | |||
353 | # Make sure a URL is "well-formed:" add a default protocol if it's missing and | ||
354 | # trim whitespace. | ||
355 | # | ||
356 | # Useful for URLs that were probably input by humans. | ||
237 | uwellform() { | 357 | uwellform() { |
238 | local u="$1" | 358 | local u="$1" |
239 | 359 | ||
@@ -246,6 +366,13 @@ uwellform() { | |||
246 | printf '%s\n' "$u" | 366 | printf '%s\n' "$u" |
247 | } | 367 | } |
248 | 368 | ||
369 | # Split a URL into its constituent parts, placing them all in the given array. | ||
370 | # | ||
371 | # The regular expression given at the top of the function ($re) is taken | ||
372 | # directly from RFC 3986, Appendix B -- and if the URL provided doesn't match | ||
373 | # it, the function bails. | ||
374 | # | ||
375 | # `usplit' takes advantage ... [CONTINUE HERE] | ||
249 | usplit() { # usplit NAME:ARRAY URL:STRING | 376 | usplit() { # usplit NAME:ARRAY URL:STRING |
250 | local re='^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' | 377 | local re='^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' |
251 | [[ $2 =~ $re ]] || return $? | 378 | [[ $2 =~ $re ]] || return $? |
@@ -408,7 +535,7 @@ pmerge() { | |||
408 | fi | 535 | fi |
409 | } | 536 | } |
410 | 537 | ||
411 | # https://github.com/dylanaraps/pure-bash-bible/ | 538 | # PBB |
412 | uencode() { # uencode URL:STRING | 539 | uencode() { # uencode URL:STRING |
413 | local LC_ALL=C | 540 | local LC_ALL=C |
414 | for ((i = 0; i < ${#1}; i++)); do | 541 | for ((i = 0; i < ${#1}; i++)); do |
@@ -425,7 +552,7 @@ uencode() { # uencode URL:STRING | |||
425 | printf '\n' | 552 | printf '\n' |
426 | } | 553 | } |
427 | 554 | ||
428 | # https://github.com/dylanaraps/pure-bash-bible/ | 555 | # PBB |
429 | udecode() { # udecode URL:STRING | 556 | udecode() { # udecode URL:STRING |
430 | : "${1//+/ }" | 557 | : "${1//+/ }" |
431 | printf '%b\n' "${_//%/\\x}" | 558 | printf '%b\n' "${_//%/\\x}" |
@@ -598,7 +725,7 @@ passthru() { | |||
598 | # convert gophermap to text/gemini (probably naive) | 725 | # convert gophermap to text/gemini (probably naive) |
599 | gopher_convert() { | 726 | gopher_convert() { |
600 | local type label path server port regex | 727 | local type label path server port regex |
601 | # cf. https://github.com/jamestomasino/dotfiles-minimal/blob/master/bin/gophermap2gemini.awk | 728 | # [GOPHER_GEMINI] |
602 | while IFS= read -r; do | 729 | while IFS= read -r; do |
603 | printf -v regex '(.)([^\t]*)(\t([^\t]*)\t([^\t]*)\t([^\t]*))?' | 730 | printf -v regex '(.)([^\t]*)(\t([^\t]*)\t([^\t]*)\t([^\t]*))?' |
604 | if [[ "$REPLY" =~ $regex ]]; then | 731 | if [[ "$REPLY" =~ $regex ]]; then |
@@ -753,7 +880,9 @@ mklesskey() { # mklesskey | |||
753 | if [[ -f "$BOLLUX_CUSTOM_LESSKEY" ]]; then | 880 | if [[ -f "$BOLLUX_CUSTOM_LESSKEY" ]]; then |
754 | log d "Using custom lesskey: '$BOLLUX_CUSTOM_LESSKEY'" | 881 | log d "Using custom lesskey: '$BOLLUX_CUSTOM_LESSKEY'" |
755 | BOLLUX_LESSKEY="${BOLLUX_CUSTOM_LESSKEY}" | 882 | BOLLUX_LESSKEY="${BOLLUX_CUSTOM_LESSKEY}" |
756 | elif [[ ! -f "$BOLLUX_LESSKEY" ]]; then | 883 | elif [[ -f "$BOLLUX_LESSKEY" ]]; then |
884 | log d "Found lesskey: '$BOLLUX_LESSKEY'" | ||
885 | else | ||
757 | log d "Generating lesskey: '$BOLLUX_LESSKEY'" | 886 | log d "Generating lesskey: '$BOLLUX_LESSKEY'" |
758 | lesskey -o "$BOLLUX_LESSKEY" - <<END | 887 | lesskey -o "$BOLLUX_LESSKEY" - <<END |
759 | #command | 888 | #command |
@@ -771,8 +900,6 @@ l right-scroll | |||
771 | ? status # 'status' will show a little help thing. | 900 | ? status # 'status' will show a little help thing. |
772 | = noaction | 901 | = noaction |
773 | END | 902 | END |
774 | else | ||
775 | log d "Found lesskey: '$BOLLUX_LESSKEY'" | ||
776 | fi | 903 | fi |
777 | } | 904 | } |
778 | 905 | ||
@@ -1104,7 +1231,7 @@ bollux_init() { | |||
1104 | HN=0 # position of history in the array | 1231 | HN=0 # position of history in the array |
1105 | run mkdir -p "${BOLLUX_HISTFILE%/*}" | 1232 | run mkdir -p "${BOLLUX_HISTFILE%/*}" |
1106 | # Remove $BOLLUX_LESSKEY and re-generate keybindings (to catch rebinds) | 1233 | # Remove $BOLLUX_LESSKEY and re-generate keybindings (to catch rebinds) |
1107 | run rm "$BOLLUX_LESSKEY" | 1234 | run rm -f "$BOLLUX_LESSKEY" |
1108 | mklesskey | 1235 | mklesskey |
1109 | } | 1236 | } |
1110 | 1237 | ||