]> git.tuebingen.mpg.de Git - gsu.git/blobdiff - funcs/gsu
gsu: Minor cosmetic cleanup.
[gsu.git] / funcs / gsu
index 81066f71b23210483e028f3d9a044dec9c9c2035..d78233ed3a8e2dab0fbaa092006f5ecc167391ff 100644 (file)
--- a/funcs/gsu
+++ b/funcs/gsu
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 # gsu -- the global subcommand utility
 # (C) 2006-2009 Andre Noll
 
 # gsu -- the global subcommand utility
 # (C) 2006-2009 Andre Noll
 
@@ -14,6 +14,7 @@ E_GSU_BAD_CONFIG_VAR          invalid config variable
 E_GSU_NEED_VALUE               value required but not given
 E_GSU_BAD_BOOL                 bad value for boolian option
 E_GSU_BAD_OPTION_TYPE          invalid option type
 E_GSU_NEED_VALUE               value required but not given
 E_GSU_BAD_BOOL                 bad value for boolian option
 E_GSU_BAD_OPTION_TYPE          invalid option type
+E_GSU_BAD_ARG_COUNT            invalid number of arguments
 E_NO_DEFAULT                   missing default value
 $gsu_errors
 "
 E_NO_DEFAULT                   missing default value
 $gsu_errors
 "
@@ -44,6 +45,37 @@ gsu_is_a_number()
 }
 export -f gsu_is_a_number
 
 }
 export -f gsu_is_a_number
 
+# Check number of arguments.
+#
+# Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
+#
+# Check that <num_given> is between <num1> and <num2> inclusively.
+# If only <num1> ist given, num2 is assumed to be infinity.
+#
+# Examples:
+#      0 0 no argument allowed
+#      1 1 exactly one argument required
+#      0 2 at most two arguments admissible
+#      2   at least two arguments reqired
+#
+gsu_check_arg_count()
+{
+       ret=-$E_GSU_BAD_ARG_COUNT
+       if [[ $# -eq 2 ]]; then # only num1 is given
+               result="at least $2 args required, $1 given"
+               [[ $1 -lt $2 ]] && return
+               ret=$GSU_SUCCESS
+               return
+       fi
+       # num1 and num2 given
+       result="need at least $2 args, $1 given"
+       [[ $1 -lt $2 ]] && return
+       result="need at most $3 args, $1 given"
+       [[ $1 -gt $3 ]] && return
+       ret=$GSU_SUCCESS
+}
+export -f gsu_check_arg_count
+
 gsu_short_msg()
 {
        echo "$1" 1>&2
 gsu_short_msg()
 {
        echo "$1" 1>&2
@@ -62,15 +94,17 @@ gsu_date_msg()
 }
 export -f gsu_date_msg
 
 }
 export -f gsu_date_msg
 
+
+
 _gsu_banner_msg()
 {
 _gsu_banner_msg()
 {
-       local txt="*** $_gsu_self --"
+       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
        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 ***"
+       gsu_short_msg "$txt ###"
 }
 export -f _gsu_banner_msg
 
 }
 export -f _gsu_banner_msg
 
@@ -99,7 +133,7 @@ export -f gsu_err_msg
 
 _gsu_usage()
 {
 
 _gsu_usage()
 {
-       gsu_short_msg "Usage: $_gsu_self command [options]"
+       gsu_short_msg "Usage: $_gsu_self command [options]"
 }
 export -f _gsu_usage
 
 }
 export -f _gsu_usage
 
@@ -141,7 +175,7 @@ Usage: prefs
 
 Print out a list of all cmt config variables, together with their current value
 and the default value."
 
 Print out a list of all cmt config variables, together with their current value
 and the default value."
-com_prefs()
+_com_prefs()
 {
        local i
 
 {
        local i
 
@@ -149,7 +183,7 @@ com_prefs()
                local name= option_type= default_value= required=
                local description= help_text=
                eval "${gsu_options[$i]}"
                local name= option_type= default_value= required=
                local description= help_text=
                eval "${gsu_options[$i]}"
-               eval val='"$'${gsu_name}_$name'"'
+               eval val='"$'${gsu_config_var_prefix}_$name'"'
                case "$required" in
                true|yes)
                        printf "# required"
                case "$required" in
                true|yes)
                        printf "# required"
@@ -163,19 +197,20 @@ com_prefs()
                        printf " [$default_value]"
                fi
                echo
                        printf " [$default_value]"
                fi
                echo
+               [[ -n "$help_text" ]] && sed -e '/^[    ]*$/d; s/^[     ]*/#    /g' <<< "$help_text"
                printf "$name=$val"
                [[ "$val" == "$default_value" ]] && printf " # default"
                echo
        done
 }
                printf "$name=$val"
                [[ "$val" == "$default_value" ]] && printf " # default"
                echo
        done
 }
-export -f com_prefs
+export -f _com_prefs
 
 export gsu_man_txt="
 Print the manual.
 
 Usage: man"
 
 
 export gsu_man_txt="
 Print the manual.
 
 Usage: man"
 
-com_man()
+_com_man()
 {
        local equal_signs="=================================================="
        local minus_signs="--------------------------------------------------"
 {
        local equal_signs="=================================================="
        local minus_signs="--------------------------------------------------"
@@ -212,7 +247,7 @@ com_man()
         done
         ret=$GSU_SUCCESS
 }
         done
         ret=$GSU_SUCCESS
 }
-export -f com_man
+export -f _com_man
 
 export gsu_help_txt="
 Print online help.
 
 export gsu_help_txt="
 Print online help.
@@ -222,19 +257,18 @@ Usage: help [command]
 Without arguments, print the list of available commands. Otherwise,
 print the help text for the given command."
 
 Without arguments, print the list of available commands. Otherwise,
 print the help text for the given command."
 
-com_help()
+_com_help()
 {
        local a b
        if test -z "$1"; then
                _gsu_banner_msg 2>&1
                _gsu_usage 2>&1
 {
        local a b
        if test -z "$1"; then
                _gsu_banner_msg 2>&1
                _gsu_usage 2>&1
-               # sed is magic, baby
-               (printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
-               printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
-               printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
-
-               grep -A 2 "^com_\([a-zA-Z_0-9]\+\)()" $0) \
-                       | grep -v -- '--' \
+               {
+                       printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
+                       printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
+                       printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
+                       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 \
                        | sed -e '/^com_\([a-zA-Z_0-9]\+\)()/bs' \
                                -e 'H;$!d;x;s/\n//g;b' \
                                -e :s \
@@ -249,7 +283,7 @@ com_help()
                                echo "$b"
                         done
                echo
                                echo "$b"
                         done
                echo
-               echo "Try $_gsu_self help <command> for info on <command>."
+               echo "Try $_gsu_self help <command> for info on <command>."
                ret=$GSU_SUCCESS
                return
        fi
                ret=$GSU_SUCCESS
                return
        fi
@@ -270,40 +304,52 @@ com_help()
        fi
        ret=$GSU_SUCCESS
        if grep -q "^com_$1()" $0; then
        fi
        ret=$GSU_SUCCESS
        if grep -q "^com_$1()" $0; then
-               sed -e "1,/com_$1()/d" -e '/^{/,$d' -e 's/^## *//' $0
+               sed -e "1,/^com_$1()$/d" -e '/^{/,$d' -e 's/^## *//' $0
                return
        fi
        _gsu_print_available_commands
        result="$1"
        ret=-$E_GSU_BAD_COMMAND
 }
                return
        fi
        _gsu_print_available_commands
        result="$1"
        ret=-$E_GSU_BAD_COMMAND
 }
-export -f com_help
+export -f _com_help
 
 # internal gsu function that syntactically checks the gsu_options array
 # for errors and parses the config file.
 _gsu_check_options()
 {
 
 # internal gsu function that syntactically checks the gsu_options array
 # for errors and parses the config file.
 _gsu_check_options()
 {
-       local i conf="${gsu_config_file:=$HOME/.$gsu_name.rc}"
+       local i conf="${gsu_config_file:=$HOME/.$gsu_name.rc}" val
+
+       for ((i=0; i < ${#gsu_options[@]}; i++)); do
+               eval "${gsu_options[$i]}"
+               eval val='"'\$$name'"'
+               eval orig_${gsu_config_var_prefix}_$name='"'${val}'"'
+       done
 
        [[ -r "$conf" ]] && source "$conf"
 
        for ((i=0; i < ${#gsu_options[@]}; i++)); do
                local name= option_type= default_value= required=
                local description= help_text=
 
        [[ -r "$conf" ]] && source "$conf"
 
        for ((i=0; i < ${#gsu_options[@]}; i++)); do
                local name= option_type= default_value= required=
                local description= help_text=
-               local val
+               local val orig_val
 
                eval "${gsu_options[$i]}"
 
 
                eval "${gsu_options[$i]}"
 
+
                # Check name. It must be non-empty and consist of [a-zA-Z_0-9]
                # only.  Moreover it must not start with [a-zA-Z].
 
                ret=-$E_GSU_BAD_CONFIG_VAR
                # Check name. It must be non-empty and consist of [a-zA-Z_0-9]
                # only.  Moreover it must not start with [a-zA-Z].
 
                ret=-$E_GSU_BAD_CONFIG_VAR
-               result="$name"
+               result="name: '$name'"
                # bash's =~ works only for 3.2 and newer, so use grep
                echo "$name" | grep '^[a-zA-Z][a-zA-Z_0123456789]*$' &> /dev/null;
                [[ $? -ne 0 ]] && return
 
                # bash's =~ works only for 3.2 and newer, so use grep
                echo "$name" | grep '^[a-zA-Z][a-zA-Z_0123456789]*$' &> /dev/null;
                [[ $? -ne 0 ]] && return
 
-               eval val='"'\$$name'"'
+               eval orig_val='"'\$orig_${gsu_config_var_prefix}_$name'"'
+               if [[ -z "$orig_val" ]]; then
+                       eval val='"'\$$name'"'
+               else
+                       val="$orig_val"
+               fi
                case "$required" in
                true|yes)
                        ret=-$E_GSU_NEED_VALUE
                case "$required" in
                true|yes)
                        ret=-$E_GSU_NEED_VALUE
@@ -311,9 +357,6 @@ _gsu_check_options()
                        [[ -z "$val" ]] && return
                        ;;
                false|no)
                        [[ -z "$val" ]] && return
                        ;;
                false|no)
-                       ret=-$E_NO_DEFAULT
-                       result="$name"
-                       [[ -z "$default_value" ]] && return
                        ;;
                *)
                        ret=-$E_GSU_BAD_BOOL
                        ;;
                *)
                        ret=-$E_GSU_BAD_BOOL
@@ -321,8 +364,7 @@ _gsu_check_options()
                        return
                esac
 
                        return
                esac
 
-               eval ${gsu_name}_$name='"'${val:=$default_value}'"'
-
+               eval ${gsu_config_var_prefix}_$name='"'${val:=$default_value}'"'
                # Check option type. ATM, only num and string are supported
                # Other types may be added without breaking compatibility
                case "$option_type" in
                # Check option type. ATM, only num and string are supported
                # Other types may be added without breaking compatibility
                case "$option_type" in
@@ -333,7 +375,7 @@ _gsu_check_options()
                        [[ $ret -lt 0 ]] && return
                        ;;
                *)
                        [[ $ret -lt 0 ]] && return
                        ;;
                *)
-                       ret=-$E_BAD_OPTION_TYPE
+                       ret=-$E_GSU_BAD_OPTION_TYPE
                        result="$name/$option_type"
                        return
                esac
                        result="$name/$option_type"
                        return
                esac
@@ -346,12 +388,26 @@ gsu()
 {
        local i
 
 {
        local i
 
+       gsu_is_a_number "${BASH_VERSINFO[0]}"
+       if [[ $ret -lt 0 ]]; then
+               gsu_msg "fatal: failed to determine bash version"
+               exit 1
+       fi
+
+       if [[ "${BASH_VERSINFO[0]}" -lt 4 ]]; then
+               gsu_msg "fatal: This script requires at least bash 4.0"
+               exit 1
+       fi
        _gsu_self="$(basename $0)"
        _gsu_self="$(basename $0)"
+       gsu_name="${gsu_name:=$_gsu_self}"
+       gsu_config_var_prefix="${gsu_config_var_prefix:=$gsu_name}"
        _gsu_init_errors
        _gsu_check_options
        if [[ "$ret" -lt 0 ]]; then
        _gsu_init_errors
        _gsu_check_options
        if [[ "$ret" -lt 0 ]]; then
-               gsu_err_msg
-               exit 1
+               if [[ "$1" != "help" && "$1" != "man" ]]; then
+                       gsu_err_msg
+                       exit 1
+               fi
        fi
        _gsu_available_commands
        gsu_cmds="$result"
        fi
        _gsu_available_commands
        gsu_cmds="$result"
@@ -362,16 +418,28 @@ gsu()
        fi
        arg="$1"
        shift
        fi
        arg="$1"
        shift
+       # check internal commands
+       if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" ]]; then
+               _com_$arg "$@"
+               if [[ "$ret" -lt 0 ]]; then
+                       gsu_err_msg
+                       exit 1
+               fi
+               exit 0
+       fi
+
+       # external commands
        for i in $gsu_cmds; do
                if test "$arg" = "$i"; then
                        com_$arg "$@"
        for i in $gsu_cmds; do
                if test "$arg" = "$i"; then
                        com_$arg "$@"
-                       if test $ret -lt 0; then
+                       if [[ "$ret" -lt 0 ]]; then
                                gsu_err_msg
                                exit 1
                        fi
                        exit 0
                fi
        done
                                gsu_err_msg
                                exit 1
                        fi
                        exit 0
                fi
        done
+
        ret=-$E_GSU_BAD_COMMAND
        result="$arg"
        gsu_err_msg
        ret=-$E_GSU_BAD_COMMAND
        result="$arg"
        gsu_err_msg