146 lines
3.6 KiB
Bash
Executable File
146 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/bash
|
|
# shellcheck disable=SC2016
|
|
set -e
|
|
export PATH="/usr/bin:/usr/local/bin"
|
|
|
|
# Copyright 2021 Rob Muhlestein <rob@rwx.gg>
|
|
# Released under Apache-2.0 license
|
|
# Please mention https://youtube.com/rwxrob
|
|
|
|
(( BASH_VERSINFO[0] < 4 )) && echo "Bash 4+ required." && exit 1
|
|
|
|
: "${PAGER:=more}"
|
|
: "${EDITOR:=vi}"
|
|
: "${HELP_BROWSER:=}"
|
|
|
|
EXE="${0##*/}"
|
|
|
|
declare -A help # associative arrays *require* declaration
|
|
|
|
help[main]='
|
|
This snippet contains the scaffolding for Bash tab completion using
|
|
the complete -C foo foo variation which allows scripts to complete
|
|
themselves (rather than having another script somewhere to manage). To
|
|
use it simply add a function with the additional command and add the
|
|
name of it to the commands array declaration at the top of the script.
|
|
Then add complete -C foo foo (or something like it) to your bashrc.
|
|
Begin functions with x_ to allow useful command names to be used that
|
|
would otherwise conflict with existing system and bash keywords. Begin
|
|
functions with x__ when you do not want them to appear with tab
|
|
completion, but still want them to be avaiable, just hidden.
|
|
'
|
|
|
|
help[foo]='The `foo` command foos.'
|
|
|
|
x_foo() {
|
|
_filter "$@" && return $?
|
|
echo "would foo: $*"
|
|
}
|
|
|
|
help[bar]='The `bar` command bars.'
|
|
|
|
x_bar() {
|
|
_filterbuf "$@" && return $?
|
|
echo "would bar: $*"
|
|
}
|
|
|
|
x__hidden() {
|
|
_filter "$@" && return $?
|
|
echo "would run _hidden: $*"
|
|
}
|
|
|
|
help[usage]='The `usage` command displays a summary of usage.'
|
|
|
|
x_usage() {
|
|
local -a cmds
|
|
for c in "${COMMANDS[@]}"; do
|
|
[[ ${c:0:1} =~ _ ]] && continue
|
|
cmds+=($c)
|
|
done
|
|
cmds="${cmds[*]}"
|
|
printf "usage: %s (%s)\n" "$EXE" "${cmds// /|}"
|
|
}
|
|
|
|
help[help]='
|
|
The `help` command prints help information. If no argument is passed
|
|
displays general help information (main). Otherwise, the documentation
|
|
for the specific argument keyword is displayed, which usually
|
|
corresponds to a command name (but not necessarily). All documentation
|
|
is written in CommonMark (Markdown) and will displayed as Web page if
|
|
`pandoc` and `$HELP_BROWSER` are detected, otherwise, just the Markdown is
|
|
sent to `$PAGER` (default: more).'
|
|
|
|
x_help() {
|
|
local name="$1"
|
|
if [[ -z "$name" ]];then
|
|
for c in "${COMMANDS[@]}";do
|
|
x_help "$c" buildonly
|
|
done
|
|
x_help main
|
|
return 0
|
|
fi
|
|
local title="$EXE $name"
|
|
[[ $name = main ]] && title="$EXE"
|
|
local file="/tmp/help-$EXE-$name.html"
|
|
if _have pandoc ; then
|
|
if _have "$HELP_BROWSER" && [[ -t 1 ]] ;then
|
|
pandoc -s --metadata title="$title" \
|
|
-o "$file" <<< "${help[$name]}"
|
|
[[ -z "$2" ]] && cd /tmp && exec "$HELP_BROWSER" "$file"
|
|
return 0
|
|
fi
|
|
pandoc -s --metadata title="$title" \
|
|
-t plain <<< "${help[$name]}" | "$PAGER"
|
|
return 0
|
|
fi
|
|
echo "${help[$name]}" | "$PAGER"
|
|
}
|
|
|
|
# --------------------- completion and delegation --------------------
|
|
|
|
_have(){ type "$1" &>/dev/null; }
|
|
|
|
_filter(){
|
|
[[ -n "$1" ]] && return 1
|
|
while IFS= read -ra args; do
|
|
"${FUNCNAME[1]}" "${args[@]}"
|
|
done
|
|
}
|
|
|
|
_filterbuf() {
|
|
[[ -n "$1" ]] && return 1
|
|
"${FUNCNAME[1]}" "$(</dev/stdin)"
|
|
}
|
|
|
|
while IFS= read -r line; do
|
|
[[ $line =~ ^declare\ -f\ x_ ]] || continue
|
|
COMMANDS+=( "${line##declare -f x_}" )
|
|
done < <(declare -F)
|
|
|
|
if [[ -n $COMP_LINE ]]; then
|
|
line=${COMP_LINE#* }
|
|
for c in "${COMMANDS[@]}"; do
|
|
[[ ${c:0:${#line}} == "${line,,}" && ${c:0:1} != _ ]] && echo "$c"
|
|
done
|
|
exit
|
|
fi
|
|
|
|
for c in "${COMMANDS[@]}"; do
|
|
if [[ $c == "$EXE" ]]; then
|
|
"x_$EXE" "$@"
|
|
exit $?
|
|
fi
|
|
done
|
|
|
|
if [[ -n "$1" ]]; then
|
|
declare cmd="$1"; shift
|
|
for c in "${COMMANDS[@]}"; do
|
|
if [[ $c == "$cmd" ]]; then
|
|
"x_$cmd" "$@"
|
|
exit $?
|
|
fi
|
|
done
|
|
fi
|
|
|
|
x_usage "$@"
|