X-Git-Url: http://git.tuebingen.mpg.de/?p=gsu.git;a=blobdiff_plain;f=funcs%2Fgsu;h=63e0acf7dfb705047efb1f4809c9af3282fbe9a3;hp=e91970ec14f73d0ec83b1213ea2a232eb49ffb6d;hb=c54761ffae2f3fd24db97a447a6db5d90959a1d6;hpb=e0cc2e967c7aa681258a4918f3d3ca92c5f86483;ds=sidebyside diff --git a/funcs/gsu b/funcs/gsu index e91970e..63e0acf 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-2011 Andre Noll _gsu_init_errors() { @@ -8,14 +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_GSU_BAD_ARG_COUNT invalid number of arguments -E_NO_DEFAULT missing default value +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 @@ -137,13 +137,16 @@ _gsu_usage() } export -f _gsu_usage +# Each line matching this is recognized as a subcommand. The name +# of the subcommand is the first subexpression. +export gsu_command_regex='^com_\([a-zA-Z_0-9]\+\)()' + _gsu_available_commands() { - result="$( (printf "help\nman\nprefs\n"; grep "^com_[a-z_]\+()" $0) \ - | sed -e 's/^com_//' -e 's/()//' \ - | sort \ - | tr '\n' ' ')" - ret=$GSU_SUCCESS + result="$({ + printf "help\nman\nprefs\n" + sed -ne "s/$gsu_command_regex/\1/g;T;p" $0 + } | sort | tr '\n' ' ')" } export -f _gsu_available_commands @@ -171,13 +174,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." +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= @@ -267,13 +284,13 @@ _com_help() 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 -A 2 "$gsu_command_regex" $0 } | grep -v -- '--' \ - | sed -e '/^com_\([a-zA-Z_0-9]\+\)()/bs' \ + | sed -e "/$gsu_command_regex/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/' \ + | sed -e "s/${gsu_command_regex}#*/\1\t/" \ | sort \ | while read a b; do printf "$a\t" @@ -304,7 +321,7 @@ _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 @@ -364,7 +381,7 @@ _gsu_check_options() return esac - eval ${gsu_config_var_prefix}_$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 @@ -384,20 +401,96 @@ _gsu_check_options() } export -f _gsu_check_options -gsu() +# Wrapper for bash's getopts. +# +# Aborts on programming errors such as missing or invalid option string. On +# success $result contains shell code that can be eval'ed. For each defined +# option x, the local variable o_x will be created when calling eval "$result". +# o_x contains true/false for options without an argument or the emtpy string/the +# given argument, depending on whether this option was contained in the "$@" +# array. +# +# Example: +# gsu_getopts abc:x:y +# eval "$result" +# [[ $ret -lt 0 ]] && return +# +# [[ "$o_a" = "true ]] && echo "The -a flag was given" +# [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c" +gsu_getopts() { - local i + local i c tab=' ' cr=' +' - gsu_is_a_number "${BASH_VERSINFO[0]}" + gsu_check_arg_count $# 1 1 if [[ $ret -lt 0 ]]; then - gsu_msg "fatal: failed to determine bash version" + gsu_err_msg exit 1 fi - if [[ "${BASH_VERSINFO[0]}" -lt 4 ]]; then - gsu_msg "fatal: This script requires at least bash 4.0" + ret=-$E_GSU_GETOPTS + result="invalid optstring $1" + if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then + gsu_err_msg exit 1 fi + + for ((i=0; i < ${#1}; i++)); do + c=${1:$i:1} + case "$c" in + [a-zA-Z:]);; + *) + ret=-$E_GSU_GETOPTS + result="invalid character $c in optstring" + gsu_err_msg + exit 1 + 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}" @@ -432,7 +525,7 @@ gsu() 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