X-Git-Url: http://git.tuebingen.mpg.de/?p=gsu.git;a=blobdiff_plain;f=misc%2Fgsu%2Fsubcommand;fp=misc%2Fgsu%2Fsubcommand;h=332e5a0d43273f352e133f4a31507b061b4bb018;hp=0000000000000000000000000000000000000000;hb=d84fb61667757b1e62b915781357e10693ce8a9e;hpb=279c1ab1336b67b144d39f1d0bbd256cd4510b20;ds=sidebyside diff --git a/misc/gsu/subcommand b/misc/gsu/subcommand new file mode 100644 index 0000000..332e5a0 --- /dev/null +++ b/misc/gsu/subcommand @@ -0,0 +1,380 @@ +#!/bin/bash +# (C) 2006-2011 Andre Noll + +if [[ $(type -t gsu_is_a_number) != "function" ]]; then + GSU_DIR=${GSU_DIR:=$HOME/.gsu} + . $GSU_DIR/common || exit 1 +fi + +_gsu_usage() +{ + gsu_short_msg "# Usage: $_gsu_self command [options]" +} +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" + sed -ne "s/$gsu_command_regex/\1/g;T;p" $0 + } | sort | tr '\n' ' ')" +} +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 + +export gsu_prefs_txt=" +Print the current preferences. + +Usage: prefs [-e] + +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 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= + local description= help_text= + eval "${gsu_options[$i]}" + eval val='"$'${gsu_config_var_prefix}_$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 + [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text" + printf "$name=$val" + [[ "$val" == "$default_value" ]] && printf " # default" + echo + done +} +export -f _com_prefs + +export gsu_man_txt=" +Print the manual. + +Usage: man" + +_com_man() +{ + local equal_signs="==================================================" + local minus_signs="--------------------------------------------------" + local com num + + echo "$_gsu_self (_${gsu_banner_txt}_) manual" + echo "${equal_signs:0:${#_gsu_self} + ${#gsu_banner_txt} + 16}" + echo + + sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//' + echo "----" + echo + echo "$_gsu_self usage" + echo "${minus_signs:0:${#_gsu_self} + 6}" + printf "\t" + _gsu_usage 2>&1 + echo "Each command has its own set of options as described below." + echo + echo "----" + echo + echo "Available commands:" + + _gsu_available_commands + for com in $result; do + num=${#com} + if test $num -lt 4; then + num=4 + fi + echo "${minus_signs:0:$num}" + echo "$com" + echo "${minus_signs:0:$num}" + $0 help $com + echo + done + ret=$GSU_SUCCESS +} +export -f _com_man + +_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 + +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 2>&1 + _gsu_usage 2>&1 + { + 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 "$gsu_command_regex" $0 + } | grep -v -- '--' \ + | 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/${gsu_command_regex}#*/\1\t/" \ + | sort \ + | while read a b; do + printf "$a\t" + if test ${#a} -lt 8; then + printf "\t" + fi + echo "$b" + done + echo + echo "# Try $_gsu_self help for info on ." + ret=$GSU_SUCCESS + return + fi + if test "$1" = "help"; then + echo "$gsu_help_txt" + ret=$GSU_SUCCESS + return + fi + if test "$1" = "man"; then + echo "$gsu_man_txt" + 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 + return + fi + _gsu_print_available_commands + result="$1" + ret=-$E_GSU_BAD_COMMAND +} +export -f _com_help + +# 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 c tab=' ' cr=' +' + + gsu_check_arg_count $# 1 1 + if [[ $ret -lt 0 ]]; then + gsu_err_msg + exit 1 + fi + + 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_setup + _gsu_available_commands + gsu_cmds="$result" + if test $# -eq 0; then + _gsu_usage + _gsu_print_available_commands + exit 1 + 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 [[ "$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 +} +export -f gsu + +# 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 +