introduce gsu: The global subcommand utility, and make bbf_adm use it.
authorAndre Noll <maan@congo.fml.local>
Wed, 11 Jul 2007 09:34:43 +0000 (11:34 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Fri, 29 Aug 2014 19:36:07 +0000 (21:36 +0200)
funcs/gsu [new file with mode: 0644]

diff --git a/funcs/gsu b/funcs/gsu
new file mode 100644 (file)
index 0000000..0403039
--- /dev/null
+++ b/funcs/gsu
@@ -0,0 +1,210 @@
+#!/bin/bash
+# gsu -- the global subcommand utility
+# (C) 2006-2007 Andre Noll
+
+gsu_init_errors()
+{
+       gsu_errors="
+GSU_SUCCESS                    success
+E_GSU_BAD_COMMAND              invalid command
+E_GSU_NOT_A_NUMBER             not a number
+$gsu_errors
+"
+       local a b i
+       local i=0
+       while read a b; do
+               if test -z "$a"; then
+                       continue
+               fi
+               #echo "a:$a,  b: $b"
+               gsu_error_txt[i]="$b"
+               eval $a=$i
+               i=$((i + 1))
+       done << EOF
+       $gsu_errors
+EOF
+}
+export -f gsu_init_errors
+
+# check if $1 is a number
+gsu_is_a_number()
+{
+       result="$1"
+       if test "$1" -eq "$1" &> /dev/null; then
+               ret=$GSU_SUCCESS
+       else
+               ret=-$E_GSU_NOT_A_NUMBER
+       fi
+}
+export -f gsu_is_a_number
+
+gsu_short_msg()
+{
+       echo "$1" 1>&2
+}
+export -f gsu_short_msg
+
+gsu_msg()
+{
+       gsu_short_msg "$gsu_self: $1"
+}
+export -f gsu_msg
+
+gsu_date_msg()
+{
+       gsu_short_msg "$gsu_self $(date): $1"
+}
+export -f gsu_date_msg
+
+gsu_banner_msg()
+{
+       local txt="*** $gsu_self --"
+       if test -z "$gsu_banner_txt"; then
+               txt="$txt set \$gsu_banner_txt to customize this message"
+       else
+               txt="$txt $gsu_banner_txt"
+       fi
+       gsu_short_msg "$txt ***"
+}
+export -f gsu_banner_msg
+
+gsu_err_msg()
+{
+       local txt="$result" err
+
+       gsu_is_a_number "$ret"
+       if test $ret -lt 0; then
+               gsu_msg "unknown error ($ret:$txt)"
+               exit 1
+       fi
+       if test $result -ge 0; then
+               gsu_msg "unknown error ($result:$txt)"
+               exit 1
+       fi
+       err=$((0 - $result))
+       if test -n "$txt"; then
+               txt="$txt: ${gsu_error_txt[$err]}"
+       else
+               txt="${gsu_error_txt[$err]}"
+       fi
+        echo "$gsu_self: $txt" 1>&2
+}
+export -f gsu_err_msg
+
+gsu_usage()
+{
+       gsu_short_msg "Usage: $gsu_self command [options]"
+}
+export -f gsu_usage
+
+export gsu_help_txt="
+Print online help.
+
+Usage: help [command]
+
+Without arguments, print the list of available commands. Otherwise,
+print the help text for the given command."
+com_help()
+{
+       local a b
+       if test -z "$1"; then
+               gsu_banner_msg
+               gsu_usage
+               # sed is magic, baby
+               grep -A 2 "^com_\([a-zA-Z_0-9]\+\)()" $0 \
+                       | grep -v -- '--' \
+                       | sed -e '/^com_\([a-zA-Z_0-9]\+\)()/bs' \
+                               -e 'H;$!d;x;s/\n//g;b' \
+                               -e :s \
+                               -e 'x;s/\n//g;${p;x;}' \
+                       | sed -e 's/^com_\([a-zA-Z_0-9]\+\)()#*/\1\t/' \
+                       | sort \
+                       | while read a b; do
+                                echo -en "$a\t"
+                                if test ${#a} -lt 8; then
+                                        echo -en "\t"
+                                fi
+                                echo "$b"
+                        done
+               echo
+               gsu_msg "Try $0 help <command> for info on <command>."
+               ret=$GSU_SUCCESS
+               return
+       fi
+       if test "$1" = "help"; then
+               gsu_short_msg "$gsu_help_txt"
+               ret=$GSU_SUCCESS
+               return
+       fi
+       ret=$GSU_SUCCESS
+       if grep -q "^com_$1()" $0; then
+               sed -e "1,/com_$1()/d" -e '/^{/,$d' -e 's/^## *//' $0
+               return
+       fi
+       gsu_print_available_commands
+       result="$1"
+       ret=-$E_GSU_BAD_COMMAND
+}
+export -f com_help
+
+gsu_available_commands()
+{
+       result="$( (echo help; grep "^com_[a-z_]\+()" $0) \
+               | sed -e 's/^com_//' -e 's/()//' \
+               | sort \
+               | tr '\n' ' ')"
+       ret=$SUCCESS
+}
+export -f gsu_available_commands
+
+gsu_print_available_commands()
+{(
+       local i count
+       gsu_short_msg "Available commands:"
+       for i in $gsu_cmds; do
+               printf "$i"
+               count=$((count + 1))
+               if test $((count % 4)) -eq 0; then
+                       echo
+               else
+                       printf "\t"
+                       if test ${#i} -lt 8; then
+                               printf "\t"
+                       fi
+               fi
+       done
+       echo
+) 2>&1
+}
+export -f gsu_print_available_commands
+
+gsu()
+{
+       gsu_self="$(basename $0)"
+       gsu_init_errors
+       gsu_available_commands
+       gsu_cmds="$result"
+       if test $# -eq 0; then
+               gsu_usage
+               gsu_print_available_commands
+               exit 1
+       fi
+       arg="$1"
+       shift
+       for i in $gsu_cmds; do
+               if test "$arg" = "$i"; then
+                       com_$arg $*
+                       if test $ret -lt 0; then
+                               gsu_err_msg
+                               exit 1
+                       fi
+                       exit 0
+               fi
+       done
+       ret=-$E_GSU_BAD_COMMAND
+       result="$arg"
+       gsu_err_msg
+       gsu_print_available_commands
+       exit 1
+}
+# no need to export this