Priliminary version of gsu2.
[gsu.git] / funcs / gsu
index 9611b30..81066f7 100644 (file)
--- a/funcs/gsu
+++ b/funcs/gsu
@@ -10,6 +10,11 @@ E_GSU_BAD_COMMAND            invalid command
 E_GSU_NOT_A_NUMBER             not a number
 E_GSU_SOURCE                   error in config file
 E_GSU_CONFIG                   bad/missing config file option
+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_NO_DEFAULT                   missing default value
 $gsu_errors
 "
        local a b i=0
@@ -100,7 +105,7 @@ export -f _gsu_usage
 
 _gsu_available_commands()
 {
-       result="$( (printf "help\nman\n"; grep "^com_[a-z_]\+()" $0) \
+       result="$( (printf "help\nman\nprefs\n"; grep "^com_[a-z_]\+()" $0) \
                | sed -e 's/^com_//' -e 's/()//' \
                | sort \
                | tr '\n' ' ')"
@@ -129,6 +134,42 @@ _gsu_print_available_commands()
 }
 export -f _gsu_print_available_commands
 
+export gsu_prefs_txt="
+Print the current preferences.
+
+Usage: prefs
+
+Print out a list of all cmt config variables, together with their current value
+and the default value."
+com_prefs()
+{
+       local i
+
+       for ((i=0; i < ${#gsu_options[@]}; i++)); do
+               local name= option_type= default_value= required=
+               local description= help_text=
+               eval "${gsu_options[$i]}"
+               eval val='"$'${gsu_name}_$name'"'
+               case "$required" in
+               true|yes)
+                       printf "# required"
+                       ;;
+               *)
+                       printf "# optional"
+                       ;;
+               esac
+               printf " $option_type: $description"
+               if [[ "$required" != "yes" && "$required" != "true" ]]; then
+                       printf " [$default_value]"
+               fi
+               echo
+               printf "$name=$val"
+               [[ "$val" == "$default_value" ]] && printf " # default"
+               echo
+       done
+}
+export -f com_prefs
+
 export gsu_man_txt="
 Print the manual.
 
@@ -190,6 +231,7 @@ com_help()
                # 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 -- '--' \
@@ -221,6 +263,11 @@ com_help()
                ret=$GSU_SUCCESS
                return
        fi
+       if test "$1" = "prefs"; then
+               echo "$gsu_prefs_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
@@ -232,51 +279,68 @@ com_help()
 }
 export -f com_help
 
-_gsu_init_config()
+# internal gsu function that syntactically checks the gsu_options array
+# for errors and parses the config file.
+_gsu_check_options()
 {
-       local name val default_val required ty comment
+       local i conf="${gsu_config_file:=$HOME/.$gsu_name.rc}"
 
-       # set default values
-       while read name default_val required ty comment; do
-               if test -z "$name"; then
-                       continue
-               fi
-               eval ${gsu_self}_$name="$default_val"
-       done << EOF
-       $gsu_config_vars
-EOF
-       result="$HOME/.${gsu_self}rc"
-       # overwrite by custom configuration
-       if [ -r "$result" ]; then
-               ret=-$E_GSU_SOURCE
-               if ! . "$result"; then
-                       gsu_err_msg
-                       exit 1
-               fi
-       fi
-       while read name default_val required ty comment; do
-               [ -z "$name" ] && continue
-               eval val="\$$name"
-               # abort if any required config var remains unset
-               ret=-$_E_GSU_CONFIG
-               if [ "$val" = "-" -a "$required" = "required" ]; then
+       [[ -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
+
+               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
+               result="$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
+
+               eval val='"'\$$name'"'
+               case "$required" in
+               true|yes)
+                       ret=-$E_GSU_NEED_VALUE
                        result="$name"
-                       gsu_err_msg
-                       exit 1
-               fi
-               if [ $ty == "number" ]; then
+                       [[ -z "$val" ]] && return
+                       ;;
+               false|no)
+                       ret=-$E_NO_DEFAULT
+                       result="$name"
+                       [[ -z "$default_value" ]] && return
+                       ;;
+               *)
+                       ret=-$E_GSU_BAD_BOOL
+                       result="required: $required, name: $name, val: $val"
+                       return
+               esac
+
+               eval ${gsu_name}_$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
+               string)
+                       ;;
+               num)
                        gsu_is_a_number "$val"
-                       if [ $ret -lt 0];  then
-                               gsu_err_msg
-                               exit 1
-                       fi
-               fi
-               eval export ${gsu_self}_$name
-       done << EOF
-       $config_vars
-EOF
+                       [[ $ret -lt 0 ]] && return
+                       ;;
+               *)
+                       ret=-$E_BAD_OPTION_TYPE
+                       result="$name/$option_type"
+                       return
+               esac
+       done
+       ret=$GSU_SUCCESS
 }
-export -f _gsu_init_config
+export -f _gsu_check_options
 
 gsu()
 {
@@ -284,7 +348,11 @@ gsu()
 
        _gsu_self="$(basename $0)"
        _gsu_init_errors
-       _gsu_init_config
+       _gsu_check_options
+       if [[ "$ret" -lt 0 ]]; then
+               gsu_err_msg
+               exit 1
+       fi
        _gsu_available_commands
        gsu_cmds="$result"
        if test $# -eq 0; then
@@ -311,3 +379,5 @@ gsu()
        exit 1
 }
 export -f gsu
+
+# TODO: gsu_strerror: get error string