X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=funcs%2Fgsu;h=abe64ce434187839f6fa97fb4bff87f8d28207b7;hb=c8f4e039d3bafb61d2d2e749160735d962e5ad6c;hp=add1be4a4567b759df60edb93e9aa658fdb1c239;hpb=8f3d6787f5d7caf3ea6f7a01ea44dd7308f005c8;p=gsu.git diff --git a/funcs/gsu b/funcs/gsu index add1be4..abe64ce 100644 --- a/funcs/gsu +++ b/funcs/gsu @@ -1,6 +1,6 @@ #!/bin/bash # gsu -- the global subcommand utility -# (C) 2006-2009 Andre Noll +# (C) 2006-2010 Andre Noll _gsu_init_errors() { @@ -8,13 +8,14 @@ _gsu_init_errors() GSU_SUCCESS success 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 +E_GSU_BAD_ARG_COUNT invalid number of arguments +E_GSU_EDITOR failed to execute editor +E_GSU_MKDIR failed to create directory +E_GSU_GETOPTS getopts error $gsu_errors " local a b i=0 @@ -44,6 +45,37 @@ gsu_is_a_number() } export -f gsu_is_a_number +# Check number of arguments. +# +# Usage: gsu_check_arg_count [] +# +# Check that is between and inclusively. +# If only 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 @@ -62,15 +94,17 @@ gsu_date_msg() } export -f gsu_date_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 - gsu_short_msg "$txt ***" + gsu_short_msg "$txt ###" } export -f _gsu_banner_msg @@ -99,7 +133,7 @@ export -f gsu_err_msg _gsu_usage() { - gsu_short_msg "Usage: $_gsu_self command [options]" + gsu_short_msg "# Usage: $_gsu_self command [options]" } export -f _gsu_usage @@ -137,13 +171,27 @@ export -f _gsu_print_available_commands export gsu_prefs_txt=" Print the current preferences. -Usage: prefs +Usage: prefs [-e] -Print out a list of all cmt config variables, together with their current value -and the default value." -com_prefs() +If -e is given, the config file is opened with the default editor. Without +options, the command prints out a list of all cmt config variables, together +with their current value and the default value." +_com_prefs() { - local i + local i conf="${gsu_config_file:=$HOME/.$gsu_name.rc}" + + if [[ "$1" = "-e" ]]; then + ret=-$E_GSU_MKDIR + result="${conf%/*}" + mkdir -p "$result" + [[ $? -ne 0 ]] && return + ret=-$E_GSU_EDITOR + result="${EDITOR:-vi}" + "$result" "$conf" + [[ $? -ne 0 ]] && return + ret=$GSU_SUCCESS + return + fi for ((i=0; i < ${#gsu_options[@]}; i++)); do local name= option_type= default_value= required= @@ -169,14 +217,14 @@ com_prefs() echo done } -export -f com_prefs +export -f _com_prefs export gsu_man_txt=" Print the manual. Usage: man" -com_man() +_com_man() { local equal_signs="==================================================" local minus_signs="--------------------------------------------------" @@ -213,7 +261,7 @@ com_man() done ret=$GSU_SUCCESS } -export -f com_man +export -f _com_man export gsu_help_txt=" Print online help. @@ -223,19 +271,18 @@ Usage: help [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 - # 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 \ @@ -250,7 +297,7 @@ com_help() echo "$b" done echo - echo "Try $_gsu_self help for info on ." + echo "# Try $_gsu_self help for info on ." ret=$GSU_SUCCESS return fi @@ -271,27 +318,33 @@ com_help() 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 } -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() { - 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= - local val + local val orig_val eval "${gsu_options[$i]}" @@ -300,12 +353,17 @@ _gsu_check_options() # 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 - 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 @@ -321,7 +379,6 @@ _gsu_check_options() esac 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 @@ -341,17 +398,78 @@ _gsu_check_options() } export -f _gsu_check_options +gsu_getopts() +{ + local i c tab=' ' cr=' +' + + gsu_check_arg_count $# 1 1 + [[ $ret -lt 0 ]] && return + + ret=-$E_GSU_GETOPTS + result="invalid optstring $1" + [[ -z "$1" || "$1" =~ "::" ]] && return + for ((i=0; i < ${#1}; i++)); do + c=${1:$i:1} + case "$c" in + [a-zA-Z:]);; + *) + result="invalid character $c in optstring" + return + esac + done + result="local opt" + for ((i=0; i < ${#1}; i++)); do + c1=${1:$i:1} + c2=${1:$(($i + 1)):1} + result+=" o_$c1" + if [[ "$c2" = ":" ]]; then + let i++ + else + result+="=false" + fi + done + result+=" + OPTIND=1 + while getopts $1 opt \"\$@\"; do + case \"\$opt\" in +" + for ((i=0; i < ${#1}; i++)); do + c1=${1:$i:1} + c2=${1:$(($i + 1)):1} + result+="$tab$tab$c1) o_$c1=" + if [[ "$c2" = ":" ]]; then + result+="\"\$OPTARG\"" + let i++ + else + result+="true" + fi + result+=";;$cr" + done + result+=" + *) + ret=-\$E_GSU_GETOPTS + result=\"invalid option given\" + return + ;; + esac + done + shift \$((\$OPTIND - 1)) +" + ret=$GSU_SUCCESS +} +export -f gsu_getopts + gsu() { local i - _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 - if [[ "$1" != "help" && "$1" != "man" && "$1" != "prefs" ]]; then + if [[ "$1" != "help" && "$1" != "man" ]]; then gsu_err_msg exit 1 fi @@ -365,16 +483,28 @@ gsu() 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 "$@" - if test $ret -lt 0; then + if [[ "$ret" -lt 0 ]]; then gsu_err_msg exit 1 fi exit 0 fi done + ret=-$E_GSU_BAD_COMMAND result="$arg" gsu_err_msg