WTF re-re-format apparently

This commit is contained in:
Case Duckworth 2021-12-11 14:34:49 -06:00
parent d1029c2573
commit cccc29e31a
1 changed files with 128 additions and 129 deletions

257
bollux Executable file → Normal file
View File

@ -93,14 +93,14 @@ bollux() {
bollux_args() {
while getopts :hvq OPT; do
case "$OPT" in
(h)
h)
bollux_usage
exit
;;
(v) BOLLUX_LOGLEVEL=DEBUG ;;
(q) BOLLUX_LOGLEVEL=QUIET ;;
(:) die 1 "Option -$OPTARG requires an argument" ;;
(*) die 1 "Unknown option: -$OPTARG" ;;
v) BOLLUX_LOGLEVEL=DEBUG ;;
q) BOLLUX_LOGLEVEL=QUIET ;;
:) die 1 "Option -$OPTARG requires an argument" ;;
*) die 1 "Unknown option: -$OPTARG" ;;
esac
done
shift $((OPTIND - 1))
@ -142,16 +142,16 @@ bollux_config() {
: "${BOLLUX_TIMEOUT:=30}" # connection timeout
: "${BOLLUX_MAXREDIR:=5}" # max redirects
: "${BOLLUX_PROTO:=gemini}" # default protocol
: "${BOLLUX_GEMINI_PORT:=1965}" # default port for gemini
: "${BOLLUX_GOPHER_PORT:=70}" # default port for gopher
: "${BOLLUX_GEMINI_PORT:=1965}" # default port for gemini
: "${BOLLUX_GOPHER_PORT:=70}" # default port for gopher
: "${BOLLUX_URL:=}" # start url
: "${BOLLUX_BYEMSG:=See You Space Cowboy ...}" # bye message
## lesskeys
: "${KEY_OPEN:=o}" # prompt for a link to open
: "${KEY_GOTO:=g}" # prompt for a page to 'goto'
: "${KEY_GOTO_FROM:=G}" # goto a page with current prefilled
: "${KEY_BACK:=[}" # go back in the history
: "${KEY_FORWARD:=]}" # go forward in the history
: "${KEY_BACK:=[}" # go back in the history
: "${KEY_FORWARD:=]}" # go forward in the history
: "${KEY_REFRESH:=r}" # refresh the page
: "${KEY_CYCLE_PRE:=p}" # cycle T_PRE_DISPLAY
: "${BOLLUX_CUSTOM_LESSKEY:=$BOLLUX_CONF_DIR/bollux.lesskey}"
@ -252,24 +252,24 @@ run() { # run COMMAND...
log() { # log LEVEL MESSAGE...
# 'QUIET' means don't log anything.
[[ "$BOLLUX_LOGLEVEL" == QUIET ]] && return
local fmt # ANSI escape code
local fmt # ANSI escape code
case "$1" in
([dD]*) # Debug level -- only print if bollux -v.
[dD]*) # Debug level -- only print if bollux -v.
[[ "$BOLLUX_LOGLEVEL" == DEBUG ]] || return
fmt=34 # Blue
fmt=34 # Blue
;;
([eE]*) # Error level -- always print.
fmt=31 # Red
[eE]*) # Error level -- always print.
fmt=31 # Red
;;
(*) # Diagnostic level -- print unless QUIET.
fmt=1 # Bold
*) # Diagnostic level -- print unless QUIET.
fmt=1 # Bold
;;
esac
shift
printf >&2 '\e[%sm%s:%-16s:\e[0m %s\n' \
"$fmt" "$PRGN" "${FUNCNAME[${LOG_FUNC:-1}]}" "$*"
"$fmt" "$PRGN" "${FUNCNAME[${LOG_FUNC:-1}]}" "$*"
}
# Exit with an error and a message describing it.
@ -298,10 +298,10 @@ list_cycle() { # list_cycle LIST<string> DELIM
# T_PRE_DISPLAY, which is user-configurable. I wanted it to be as easy
# to configure for users who might not immediately know the bash array
# syntax, but can figure out 'variable=value' without much thought.
local list="${!1}" # Pass the list by name, not value
local delim="$2" # The delimiter of the string
local list="${!1}" # Pass the list by name, not value
local delim="$2" # The delimiter of the string
local first="${list%%${delim}*}" # The first element
local rest="${list#*${delim}}" # The rest of the elements
local rest="${list#*${delim}}" # The rest of the elements
# -v prints to the variable specified.
printf -v "$1" '%s%s%s' "${rest}" "${delim}" "${first}"
}
@ -325,7 +325,7 @@ prompt() { # prompt [-u] PROMPT [READ_ARGS...]
read_cmd+=(-i "$BOLLUX_URL")
shift
fi
local prompt="$1" # How to prompt the user
local prompt="$1" # How to prompt the user
shift
read_cmd+=(-p "$prompt> ")
"${read_cmd[@]}" </dev/tty "$@"
@ -423,11 +423,11 @@ usplit() { # usplit URL_ARRAY<name> URL
# below performs a reverse lookup on the name to get the actual data.
# shellcheck disable=2034
local entire_url="${BASH_REMATCH[0]}" \
scheme="${BASH_REMATCH[2]}" \
authority="${BASH_REMATCH[4]}" \
path="${BASH_REMATCH[5]}" \
query="${BASH_REMATCH[7]}" \
fragment="${BASH_REMATCH[9]}"
scheme="${BASH_REMATCH[2]}" \
authority="${BASH_REMATCH[4]}" \
path="${BASH_REMATCH[5]}" \
query="${BASH_REMATCH[7]}" \
fragment="${BASH_REMATCH[9]}"
# Iterate through the 5 components of a URL and assign them to elements
# of URL_ARRAY, as follows:
@ -516,10 +516,10 @@ ucblank() { # ucblank COMPONENT<name>
# `ucset' sets one component of a URL array and setting the 0th element to the
# new full URL. Use it instead of directly setting the array element with U[x],
# because U[0] will fall out of sync with the rest of the contents.
ucset() { # ucset URL_ARRAY_INDEX<name> NEW_VALUE
ucset() { # ucset URL_ARRAY_INDEX<name> NEW_VALUE
local url_array_component="$1" # Of form 'URL_ARRAY[INDEX]'
local value="$2"
# Assign $value to $url_array_component.
#
# Wrapped in an 'eval' for the extra layer of indirection.
@ -538,8 +538,8 @@ uencode() { # uencode URL
for ((i = 0; i < ${#1}; i++)); do
: "${1:i:1}"
case "$_" in
([a-zA-Z0-9.~_-]) printf '%s' "$_" ;;
(*) printf '%%%02X' "'$_" ;;
[a-zA-Z0-9.~_-]) printf '%s' "$_" ;;
*) printf '%%%02X' "'$_" ;;
esac
done
printf '\n'
@ -704,7 +704,6 @@ gemini_request() { # gemini_request URL
port="$BOLLUX_GEMINI_PORT"
fi
# Build the SSL command to request the resource.
#
# This is the beating heart of bollux, the command that does all the
@ -716,12 +715,12 @@ gemini_request() { # gemini_request URL
# manual [9] it says not to use it, but who reads the manual,
# anyway?
openssl s_client
-crlf # Automatically add CR+LF to line
-quiet # Don't print all the cert stuff
-crlf # Automatically add CR+LF to line
-quiet # Don't print all the cert stuff
# -ign_eof # `-quiet' implies `-ign_eof'
-connect "${url[2]}:$port" # The server and port to connect
-servername "${url[2]}" # SNI: Server Name Identification
-no_ssl3 -no_tls1 -no_tls1_1 # disable old TLS/SSL versions
-connect "${url[2]}:$port" # The server and port to connect
-servername "${url[2]}" # SNI: Server Name Identification
-no_ssl3 -no_tls1 -no_tls1_1 # disable old TLS/SSL versions
)
# Actually request the resource.
@ -733,9 +732,9 @@ gemini_request() { # gemini_request URL
# Handle the gemini response - see [3] Section 3.
gemini_response() { # gemini_response URL
local code meta # received on the first line of the response
local title # determined by a clunky heuristic, see read loop: (2*)
local url="$1" # the currently-visited URL.
local code meta # received on the first line of the response
local title # determined by a clunky heuristic, see read loop: (2*)
local url="$1" # the currently-visited URL.
# Read the first line.
#
@ -751,7 +750,7 @@ gemini_response() { # gemini_response URL
# `download', below), but I'm not sure how to remedy that issue either.
# It requires more research.
while read -t "$BOLLUX_TIMEOUT" -r code meta ||
{ (($? > 128)) && die 99 "Timeout."; }; do
{ (($? > 128)) && die 99 "Timeout."; }; do
break
done
log d "[$code] $meta"
@ -763,20 +762,20 @@ gemini_response() { # gemini_response URL
# - I branch on the first digit of the status code, instead of both, to
# minimize the amount of duplicated code I need to write.
case "$code" in
(1*) # INPUT
1*) # INPUT
# Gemini allows GET-style requests, and the INPUT family of
# response codes facilitate them. `10' is for standard input,
# and `11' is for sensitive information, like passwords.
REDIRECTS=0
BOLLUX_URL="$url"
case "$code" in
(10) run prompt "$meta" ;;
(11) run prompt "$meta" -s ;; # sensitive input
10) run prompt "$meta" ;;
11) run prompt "$meta" -s ;; # sensitive input
esac
run history_append "$url" "${title:-}"
run blastoff "?$(uencode "$REPLY")"
;;
(2*) # OK
2*) # OK
# The `20' family of requests is like HTTP's `200' family: it
# means that the request worked and the server is sending the
# requested content.
@ -811,7 +810,7 @@ gemini_response() { # gemini_response URL
passthru
} | run display "$meta" "${title:-}"
;;
(3*) # REDIRECT
3*) # REDIRECT
# Redirects are a fundamental part of any hypertext framework,
# and if I remember correctly, one of the main reasons
# solderpunk and others began thinking about gemini (the others
@ -838,51 +837,51 @@ gemini_response() { # gemini_response URL
# will also be an option, however.
run blastoff "$meta" # TODO: confirm redirect
;;
(4*) # TEMPORARY ERROR
4*) # TEMPORARY ERROR
# Since the 4* codes ([3] Appendix 1) are all server issues,
# bollux can treat them all basically the same. This is an area
# that could use some expansion.
local desc="Temporary error"
case "$code" in
(41) desc+=" (server unavailable)" ;;
(42) desc+=" (CGI error)" ;;
(43) desc+=" (proxy error)" ;;
(44) desc+=" (slow down)" ;; # could be particularly improved
41) desc+=" (server unavailable)" ;;
42) desc+=" (CGI error)" ;;
43) desc+=" (proxy error)" ;;
44) desc+=" (slow down)" ;; # could be particularly improved
esac
REDIRECTS=0
die "$((100 + code))" "$desc [$code]: $meta"
;;
(5*) # PERMANENT ERROR
5*) # PERMANENT ERROR
# The situation with the 5* codes is basically similar to the 4*
# codes. It could maybe use more thought as to what behavior to
# implement. Maybe adding the (bad) requests to history,
# subject to configuration?
local desc="Permanent failure"
case "$code" in
(51) desc+=" (not found)" ;;
(52) desc+=" (gone)" ;;
(53) desc+=" (proxy request refused)" ;;
# For some reason, codes 54--58 inclusive aren't used.
(59) desc+=" (bad request)" ;;
51) desc+=" (not found)" ;;
52) desc+=" (gone)" ;;
53) desc+=" (proxy request refused)" ;;
# For some reason, codes 54--58 inclusive aren't used.
59) desc+=" (bad request)" ;;
esac
REDIRECTS=0
die "$((100 + code))" "$desc [$code]: $meta"
;;
(6*) # CERTIFICATE ERROR (TODO)
6*) # CERTIFICATE ERROR (TODO)
# Dealing with certificates is honestly the most important
# feature missing from bollux to get it to 1.0. Right now,
# bollux deals with 6* status codes identically to 4* and 5*
# codes. This is not ideal, in the slightest.
local desc="Client certificate required"
case "$code" in
(61) desc+=" (certificate not authorized)" ;;
(62) desc+=" (certificate not valid)" ;;
61) desc+=" (certificate not authorized)" ;;
62) desc+=" (certificate not valid)" ;;
esac
REDIRECTS=0
log d "Not implemented: Client certificates"
die "$((100 + code))" "[$code] $meta"
;;
(*) # UNKNOWN
*) # UNKNOWN
# Just in case we get a weird, un-spec-compliant status code.
[[ -z "${code-}" ]] && die 100 "Empty response code."
die "$((100 + code))" "Unknown response code: $code."
@ -916,9 +915,9 @@ gopher_request() { # gopher_request URL
# [7] Section 2.1
[[ "$url" =~ gopher://([^/?#:]*)(:([0-9]+))?(/((.))?(/?.*))?$ ]]
local server="${BASH_REMATCH[1]}" \
port="${BASH_REMATCH[3]:-$BOLLUX_GOPHER_PORT}" \
type="${BASH_REMATCH[6]:-1}" \
path="${BASH_REMATCH[7]}"
port="${BASH_REMATCH[3]:-$BOLLUX_GOPHER_PORT}" \
type="${BASH_REMATCH[6]:-1}" \
path="${BASH_REMATCH[7]}"
log d "URL='$url' SERVER='$server' TYPE='$type' PATH='$path'"
# Bash has this really neat feature where it can open a TCP socket
@ -952,25 +951,25 @@ gopher_response() { # gopher_response URL
# text-ish, it only concerns itself with those in this case statement.
# All the others are simply downloaded.
case "$type" in
(0) # Item is a file
0) # Item is a file
# Since gopher doesn't send MIME-type information in-band, we
# just assume it's text/plain, and try to convert it later to
# UTF-8 with `iconv'.
run display text/plain
;;
(1) # Item is a directory [gophermap]
1) # Item is a directory [gophermap]
# Since I've already written all the code to typeset gemini
# well, it's easy to convert a gophermap to text/gemini and
# display it than to write a whole new gophermap typesetter.
run gopher_convert | run display text/gemini
;;
(3) # Error
3) # Error
# I don't know all the gopher error cases, and the spec is
# pretty quiet on them. So bollux just signals failure and
# bails.
die 203 "GOPHER: failed"
;;
(7) # Item is an Index-Search server
7) # Item is an Index-Search server
# Gopher search queries are separated from their resources by a
# TAB. It's wild.
if [[ "$url" =~ $'\t' ]]; then
@ -980,7 +979,7 @@ gopher_response() { # gopher_response URL
run blastoff "$url $REPLY"
fi
;;
(*) # Anything else
*) # Anything else
# The list at [6] Section 3.8 includes the following (noted where it
# might be good to differently handle them in the future):
#
@ -1030,19 +1029,19 @@ gopher_convert() {
continue
fi
case "$type" in
(.) # end of file
.) # end of file
printf '.\n'
break
;;
(i) # label
i) # label
case "$label" in
('#'* | '*'[[:space:]]*)
'#'* | '*'[[:space:]]*)
if $pre; then
printf '%s\n' '```'
pre=false
fi
;;
(*)
*)
if ! $pre; then
printf '%s\n' '```'
pre=true
@ -1051,28 +1050,28 @@ gopher_convert() {
esac
printf '%s\n' "$label"
;;
(h) # html link
h) # html link
if $pre; then
printf '%s\n' '```'
pre=false
fi
printf '=> %s %s\n' "${path:4}" "$label"
;;
(T) # telnet link
T) # telnet link
if $pre; then
printf '%s\n' '```'
pre=false
fi
printf '=> telnet://%s:%s/%s%s %s\n' \
"$server" "$port" "$type" "$path" "$label"
"$server" "$port" "$type" "$path" "$label"
;;
(*) # other type
*) # other type
if $pre; then
printf '%s\n' '```'
pre=false
fi
printf '=> gopher://%s:%s/%s%s %s\n' \
"$server" "$port" "$type" "$path" "$label"
"$server" "$port" "$type" "$path" "$label"
;;
esac
done
@ -1109,7 +1108,7 @@ display() { # display METADATA [TITLE]
for ((i = 1; i <= "${#hdr[@]}"; i++)); do
h="${hdr[$i]}"
case "$h" in
(*charset=*) charset="${h#*=}" ;;
*charset=*) charset="${h#*=}" ;;
esac
done
@ -1119,7 +1118,7 @@ display() { # display METADATA [TITLE]
log debug "mime='$mime'; charset='$charset'"
case "$mime" in
(text/*)
text/*)
set_title "$title${title:+ - }bollux"
# Build the `less' command
less_cmd=(less)
@ -1163,7 +1162,7 @@ display() { # display METADATA [TITLE]
run "${less_cmd[@]}" && bollux_quit
} || run handle_keypress "$?"
;;
(*) run download "$BOLLUX_URL" ;;
*) run download "$BOLLUX_URL" ;;
esac
}
@ -1173,8 +1172,8 @@ less_prompt_escape() { # less_prompt_escape STRING
for ((i = 0; i < ${#1}; i++)); do
: "${1:i:1}"
case "$_" in
([\?:\.%\\]) printf '\%s' "$_" ;;
(*) printf '%s' "$_" ;;
[\?:\.%\\]) printf '\%s' "$_" ;;
*) printf '%s' "$_" ;;
esac
done
printf '\n'
@ -1232,7 +1231,7 @@ typeset_gemini() {
while IFS= read -r; do
case "$REPLY" in
('```'*)
'```'*)
PRE_LINE_FORCE=false
if $pre; then
pre=false
@ -1240,28 +1239,28 @@ typeset_gemini() {
pre=true
fi
case "${T_PRE_DISPLAY%%,*}" in
(pre)
pre)
:
;;
(alt | both)
alt | both)
$pre && PRE_LINE_FORCE=true \
gemini_pre "${REPLY#\`\`\`}"
gemini_pre "${REPLY#\`\`\`}"
;;
esac
continue
;;
('=>'*)
'=>'*)
: $((ln += 1))
gemini_link "$REPLY" $pre "$ln"
;;
('#'*) gemini_header "$REPLY" $pre ;;
('*'[[:space:]]*)
'#'*) gemini_header "$REPLY" $pre ;;
'*'[[:space:]]*)
gemini_list "$REPLY" $pre
;;
('>'*)
'>'*)
gemini_quote "$REPLY" $pre
;;
(*) gemini_text "$REPLY" $pre ;;
*) gemini_text "$REPLY" $pre ;;
esac
done
}
@ -1282,13 +1281,13 @@ gemini_link() {
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
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")"
-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 + ${#ln} + 2))" \
"$WIDTH" "$a"
-A "${C_RESET}" \
-l "$((${#ln} + 3 + ${#t}))" \
-m "$((T_MARGIN + ${#ln} + 2))" \
"$WIDTH" "$a"
else
gemini_pre "$1"
fi
@ -1306,7 +1305,7 @@ gemini_header() {
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
fold_line -B "\e[${hdrfmt}m" -A "${C_RESET}" -m "${T_MARGIN}" \
"$WIDTH" "$t"
"$WIDTH" "$t"
else
gemini_pre "$1"
fi
@ -1321,7 +1320,7 @@ gemini_list() {
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
fold_line -B "\e[${C_LIST}m" -A "${C_RESET}" -m "$T_MARGIN" \
"$WIDTH" "$t"
"$WIDTH" "$t"
else
gemini_pre "$1"
fi
@ -1336,7 +1335,7 @@ gemini_quote() {
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
fold_line -B "\e[${C_QUOTE}m" -A "${C_RESET}" -m "$T_MARGIN" \
"$WIDTH" "$t"
"$WIDTH" "$t"
else
gemini_pre "$1"
fi
@ -1346,7 +1345,7 @@ gemini_text() {
if ! ${2-false}; then
printf "%${S_MARGIN}s " ' '
fold_line -m "$T_MARGIN" \
"$WIDTH" "$1"
"$WIDTH" "$1"
else
gemini_pre "$1"
fi
@ -1370,25 +1369,25 @@ fold_line() { # fold_line [OPTIONS...] WIDTH TEXT
OPTIND=0
while getopts nm:f:l:B:A: OPT; do
case "$OPT" in
(n) # -n = no trailing newline
n) # -n = no trailing newline
newline=false
;;
(m) # -m MARGIN = margin for all lines
m) # -m MARGIN = margin for all lines
margin_all="$OPTARG"
;;
(f) # -f MARGIN = margin for first line
f) # -f MARGIN = margin for first line
margin_first="$OPTARG"
;;
(l) # -l LENGTH = length of line before starting fold
l) # -l LENGTH = length of line before starting fold
ll="$OPTARG"
;;
(B) # -B BEFORE = text to insert before each line
B) # -B BEFORE = text to insert before each line
before="$OPTARG"
;;
(A) # -A AFTER = text to insert after each line
A) # -A AFTER = text to insert after each line
after="$OPTARG"
;;
(*) return 1 ;;
*) return 1 ;;
esac
done
shift "$((OPTIND - 1))"
@ -1426,37 +1425,37 @@ fold_line() { # fold_line [OPTIONS...] WIDTH TEXT
# use the exit code from less (see mklesskey) to do things
handle_keypress() { # handle_keypress CODE
case "$1" in
(48) # o - open a link -- show a menu of links on the page
48) # o - open a link -- show a menu of links on the page
run select_url "$BOLLUX_PAGESRC"
;;
(49) # g - goto a url -- input a new url
49) # g - goto a url -- input a new url
prompt GO
run blastoff -u "$REPLY"
;;
(50) # [ - back in the history
50) # [ - back in the history
run history_back || {
sleep 0.5
run blastoff "$BOLLUX_URL"
}
;;
(51) # ] - forward in the history
51) # ] - forward in the history
run history_forward || {
sleep 0.5
run blastoff "$BOLLUX_URL"
}
;;
(52) # r - re-request the current resource
52) # r - re-request the current resource
run blastoff "$BOLLUX_URL"
;;
(53) # G - goto a url (pre-filled with current)
53) # G - goto a url (pre-filled with current)
run prompt -u GO
run blastoff -u "$REPLY"
;;
(54) # ` - change alt-text visibility and refresh
54) # ` - change alt-text visibility and refresh
run list_cycle T_PRE_DISPLAY ,
run blastoff "$BOLLUX_URL"
;;
(55) # 55-57 -- still available for binding
55) # 55-57 -- still available for binding
die "$?" "less(1) error"
;;
esac
@ -1473,8 +1472,8 @@ select_url() { # select_url FILE
PS3="OPEN> "
select u in "${MAPFILE[@]}"; do
case "$REPLY" in
(q) bollux_quit ;;
([^0-9]*) run blastoff -u "$REPLY" && break ;;
q) bollux_quit ;;
[^0-9]*) run blastoff -u "$REPLY" && break ;;
esac
run blastoff "${u%%[[:space:]]*}" && break
done </dev/tty
@ -1543,12 +1542,12 @@ history_append() { # history_append URL TITLE
# Print the URL and its title (if given) to $BOLLUX_HISTFILE.
local fmt=''
fmt+='%(%FT%T)T\t' # %(_)T calls directly to 'strftime'.
if (( $# == 2 )); then
fmt+='%s\t' # $url
fmt+='%s\n' # $title
fmt+='%(%FT%T)T\t' # %(_)T calls directly to 'strftime'.
if (($# == 2)); then
fmt+='%s\t' # $url
fmt+='%s\n' # $title
else
fmt+='%s%s\n' # printf needs a field for every argument.
fmt+='%s%s\n' # printf needs a field for every argument.
fi
run printf -- "$fmt" -1 "$url" "$title" >>"$BOLLUX_HISTFILE"
@ -1567,26 +1566,26 @@ history_back() {
# one with each call to `history_append'. If we subtract 1, we'll just
# be at the end of the array again, reloading the page.
((HN -= 2))
if ((HN < 0)); then
HN=0
log e "Beginning of history."
return 1
fi
run blastoff "${HISTORY[$HN]}"
}
# Move forward in session history.
history_forward() {
log d "HN=$HN"
if ((HN >= ${#HISTORY[@]})); then
HN="${#HISTORY[@]}"
log e "End of history."
return 1
fi
run blastoff "${HISTORY[$HN]}"
}
@ -1646,8 +1645,8 @@ blastoff() { # blastoff [-u] URL
run "${url[1]}_response" "$url"
else
log d \
"No response handler for '${url[1]}';" \
" passing thru"
"No response handler for '${url[1]}';" \
" passing thru"
passthru
fi
}