#!/usr/bin/bash # shellcheck disable=SC2016 set -e export PATH="/usr/bin:/usr/local/bin" # Copyright 2021 Rob Muhlestein # 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]}" "$(