forked from acdw/bollux
parent
7582c32cf7
commit
0ceec7766d
114
bollux
114
bollux
|
@ -59,15 +59,15 @@ bollux_usage() {
|
|||
cat <<END
|
||||
$PRGN (v. $VRSN): a bash gemini client
|
||||
usage:
|
||||
$PRGN [-h]
|
||||
$PRGN [-q] [-v] [URL]
|
||||
$PRGN [-h]
|
||||
$PRGN [-q] [-v] [URL]
|
||||
flags:
|
||||
-h show this help and exit
|
||||
-q be quiet: log no messages
|
||||
-v be verbose: log more messages
|
||||
-h show this help and exit
|
||||
-q be quiet: log no messages
|
||||
-v be verbose: log more messages
|
||||
parameters:
|
||||
URL the URL to start in
|
||||
If not provided, the user will be prompted.
|
||||
URL the URL to start in
|
||||
If not provided, the user will be prompted.
|
||||
END
|
||||
}
|
||||
|
||||
|
@ -1128,15 +1128,23 @@ display() { # display METADATA [TITLE]
|
|||
text/*)
|
||||
set_title "$title${title:+ - }bollux"
|
||||
# Build the `less' command
|
||||
less_cmd=(less)
|
||||
# Render ANSI color escapes ONLY (as opposed to `-r', which
|
||||
# renders all escapes)
|
||||
less_cmd+=(-R)
|
||||
# Don't wrap text. `fold_line' takes care of wrapping normal
|
||||
# text, and pre-formatted text shouldn't wrap.
|
||||
less_cmd+=(-S)
|
||||
less_cmd=(less
|
||||
# Render ANSI color escapes ONLY (as opposed to `-r', which
|
||||
# renders all escapes)
|
||||
-R
|
||||
# Don't wrap text. `fold_line' takes care of wrapping normal
|
||||
# text, and pre-formatted text shouldn't wrap.
|
||||
-S
|
||||
# float content to the top of the window
|
||||
+k
|
||||
)
|
||||
|
||||
# Load the keybindings (see `lesskey').
|
||||
mklesskey && less_cmd+=(-k "$BOLLUX_LESSKEY")
|
||||
|
||||
# less displays a "prompt" at the bottom of the screen that's
|
||||
# customizable. bollux uses it to show the URL of the current page, or
|
||||
# a helpful keybinding line when the user presses "?".
|
||||
local helpline="${KEY_OPEN}:open, "
|
||||
helpline+="${KEY_GOTO}/"
|
||||
helpline+="${KEY_GOTO_FROM}:goto, "
|
||||
|
@ -1150,25 +1158,44 @@ display() { # display METADATA [TITLE]
|
|||
-P="$(less_prompt_escape "$helpline")$"
|
||||
# start with statusline
|
||||
-m
|
||||
# float content to the top
|
||||
+k
|
||||
)
|
||||
|
||||
local typeset
|
||||
# Decide how to typeset the resource by the MIME part after the '/'.
|
||||
# I.e., 'text/gemini' is passed to `typeset_gemini', 'text/gopher' is
|
||||
# passed to `typeset_gopher', etc. If the function doesn't exist
|
||||
# (`declare -Fp' errors), just use `passthru'.
|
||||
local typeset_func
|
||||
local submime="${mime#*/}"
|
||||
if declare -Fp "typeset_$submime" &>/dev/null; then
|
||||
typeset="typeset_$submime"
|
||||
typeset_func="typeset_$submime"
|
||||
else
|
||||
typeset="passthru"
|
||||
typeset_func="passthru"
|
||||
fi
|
||||
|
||||
# Display the resource from stdin
|
||||
{
|
||||
# Convert the charset to UTF-8
|
||||
run iconv -f "${charset^^}" -t "UTF-8" |
|
||||
# Save it to BOLLUX_PAGESRC, for picking out links (see
|
||||
# `select_url')
|
||||
run tee "$BOLLUX_PAGESRC" |
|
||||
run "$typeset" | #cat
|
||||
# Typeset the resource
|
||||
run "$typeset_func" |
|
||||
# Show on the screen with `less'
|
||||
run "${less_cmd[@]}" && bollux_quit
|
||||
} || run handle_keypress "$?"
|
||||
} ||
|
||||
# `less' has a weird custom keybinding thing where you can customize
|
||||
# its exit codes, somewhat, by pressing certain keys. Bollux
|
||||
# (ab)uses this funcitonality to be more interactive. If `less'
|
||||
# exits with success, bollux quits. But if it exits with an error
|
||||
# code, this `||' clause handles the keypress by inspecting less's
|
||||
# exit code.
|
||||
run handle_keypress "$?"
|
||||
;;
|
||||
# Bollux can only actually handle text/* MIME types. Anything else it
|
||||
# passes to `download', which just downloads the resource using `dd' --
|
||||
# sometimes it works, sometimes it doesn't. FIXME: `download' should be
|
||||
# customizable, and probably default to something more gemini-friendly.
|
||||
*) run download "$BOLLUX_URL" ;;
|
||||
esac
|
||||
}
|
||||
|
@ -1214,17 +1241,21 @@ END
|
|||
fi
|
||||
}
|
||||
|
||||
# typeset a text/gemini document
|
||||
# Typeset a text/gemini document.
|
||||
#
|
||||
# `typeset_gemini' reads the input line-by-line, calling out to the helper
|
||||
# functions below depending on what type the line is.
|
||||
typeset_gemini() {
|
||||
local pre=false
|
||||
local ln=0 # link number
|
||||
local pre=false # "The only state a parser needs to maintain."
|
||||
local ln=0 # link number
|
||||
|
||||
# Figure out what width to fold text at.
|
||||
if ((T_WIDTH == 0)); then
|
||||
shopt -s checkwinsize
|
||||
(
|
||||
:
|
||||
:
|
||||
) # dumb formatting brought to you by shfmt
|
||||
) # hacky micro-sleep to refresh winsize variables
|
||||
log d "LINES=$LINES; COLUMNS=$COLUMNS"
|
||||
T_WIDTH=$COLUMNS
|
||||
fi
|
||||
|
@ -1239,6 +1270,8 @@ typeset_gemini() {
|
|||
while IFS= read -r; do
|
||||
case "$REPLY" in
|
||||
'```'*)
|
||||
# Preformatted toggle lines are somewhat complicated by the
|
||||
# `T_PRE_DISPLAY' customization variable.
|
||||
PRE_LINE_FORCE=false
|
||||
if $pre; then
|
||||
pre=false
|
||||
|
@ -1246,9 +1279,7 @@ typeset_gemini() {
|
|||
pre=true
|
||||
fi
|
||||
case "${T_PRE_DISPLAY%%,*}" in
|
||||
pre)
|
||||
:
|
||||
;;
|
||||
pre) : ;;
|
||||
alt | both)
|
||||
$pre && PRE_LINE_FORCE=true \
|
||||
gemini_pre "${REPLY#\`\`\`}"
|
||||
|
@ -1272,7 +1303,7 @@ typeset_gemini() {
|
|||
done
|
||||
}
|
||||
|
||||
gemini_link() {
|
||||
gemini_link() { # gemini_link LINE IN_PRE LINK_NUMBER
|
||||
local re="^(=>)[[:blank:]]*([^[:blank:]]+)[[:blank:]]*(.*)"
|
||||
local s t a # sigil, text, annotation(url)
|
||||
local ln="$3"
|
||||
|
@ -1300,7 +1331,7 @@ gemini_link() {
|
|||
fi
|
||||
}
|
||||
|
||||
gemini_header() {
|
||||
gemini_header() { # gemini_header LINE IN_PRE
|
||||
local re="^(#+)[[:blank:]]*(.*)"
|
||||
local s t a # sigil, text, annotation(lvl)
|
||||
if ! ${2-false} && [[ "$1" =~ $re ]]; then
|
||||
|
@ -1318,7 +1349,7 @@ gemini_header() {
|
|||
fi
|
||||
}
|
||||
|
||||
gemini_list() {
|
||||
gemini_list() { # gemini_list LINE IN_PRE
|
||||
local re="^(\*)[[:blank:]]*(.*)"
|
||||
local s t # sigil, text
|
||||
if ! ${2-false} && [[ "$1" =~ $re ]]; then
|
||||
|
@ -1333,7 +1364,7 @@ gemini_list() {
|
|||
fi
|
||||
}
|
||||
|
||||
gemini_quote() {
|
||||
gemini_quote() { # gemini_quote LINE IN_PRE
|
||||
local re="^(>)[[:blank:]]*(.*)"
|
||||
local s t # sigil, text
|
||||
if ! ${2-false} && [[ "$1" =~ $re ]]; then
|
||||
|
@ -1348,7 +1379,7 @@ gemini_quote() {
|
|||
fi
|
||||
}
|
||||
|
||||
gemini_text() {
|
||||
gemini_text() { # gemini_text IN_PRE
|
||||
if ! ${2-false}; then
|
||||
printf "%${S_MARGIN}s " ' '
|
||||
fold_line -m "$T_MARGIN" \
|
||||
|
@ -1358,7 +1389,7 @@ gemini_text() {
|
|||
fi
|
||||
}
|
||||
|
||||
gemini_pre() {
|
||||
gemini_pre() { # gemini_pre LINE
|
||||
# Print preformatted text, dependent on $T_PRE_DISPLAY and
|
||||
# $PRE_LINE_FORCE
|
||||
if [[ alt != "${T_PRE_DISPLAY%%,*}" ]] || $PRE_LINE_FORCE; then
|
||||
|
@ -1367,7 +1398,7 @@ gemini_pre() {
|
|||
fi
|
||||
}
|
||||
|
||||
# wrap lines on words to WIDTH
|
||||
# Wrap lines, on word boundaries, to WIDTH.
|
||||
fold_line() { # fold_line [OPTIONS...] WIDTH TEXT
|
||||
# see getopts, below, for options
|
||||
local newline=true
|
||||
|
@ -1429,7 +1460,9 @@ fold_line() { # fold_line [OPTIONS...] WIDTH TEXT
|
|||
$newline && printf '\n'
|
||||
}
|
||||
|
||||
# use the exit code from less (see mklesskey) to do things
|
||||
# HANDLE KEYPRESSES ############################################################
|
||||
|
||||
# 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
|
||||
|
@ -1462,13 +1495,16 @@ handle_keypress() { # handle_keypress CODE
|
|||
run list_cycle T_PRE_DISPLAY ,
|
||||
run blastoff "$BOLLUX_URL"
|
||||
;;
|
||||
55) # 55-57 -- still available for binding
|
||||
55 | 56 | 57) # 55-57 -- still available for binding
|
||||
die "$?" "Unknown keybinding"
|
||||
;;
|
||||
*) # some other less error
|
||||
die "$?" "less(1) error"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# select a URL from a text/gemini file
|
||||
# Select a URL from a text/gemini file, using `mapfile' and `select'.
|
||||
select_url() { # select_url FILE
|
||||
run mapfile -t < <(extract_links <"$1")
|
||||
if ((${#MAPFILE[@]} == 0)); then
|
||||
|
@ -1486,7 +1522,7 @@ select_url() { # select_url FILE
|
|||
done </dev/tty
|
||||
}
|
||||
|
||||
# extract the links from a text/gemini file
|
||||
# Extract the links from a text/gemini file
|
||||
extract_links() {
|
||||
local url alt
|
||||
local re="^=>[[:space:]]*([^[:space:]]+)([[:space:]]+(.*))?$"
|
||||
|
|
Loading…
Reference in New Issue