2 # gsu -- the global subcommand utility
3 # (C) 2006-2009 Andre Noll
9 E_GSU_BAD_COMMAND invalid command
10 E_GSU_NOT_A_NUMBER not a number
11 E_GSU_SOURCE error in config file
12 E_GSU_CONFIG bad/missing config file option
13 E_GSU_BAD_CONFIG_VAR invalid config variable
14 E_GSU_NEED_VALUE value required but not given
15 E_GSU_BAD_BOOL bad value for boolian option
16 E_GSU_BAD_OPTION_TYPE invalid option type
17 E_GSU_BAD_ARG_COUNT invalid number of arguments
18 E_NO_DEFAULT missing default value
34 export -f _gsu_init_errors
36 # check if $1 is a number
40 if test "$1" -eq "$1" &> /dev/null; then
43 ret=-$E_GSU_NOT_A_NUMBER
46 export -f gsu_is_a_number
48 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
50 # If only <num1> ist given, then <num_given> must equal <num1>.
51 # Otherwise, <num1>..<num2> is treated as a range and it is checked
52 # that <num_given> lies between <num1> and <num2> inclusively.
55 ret=-$E_GSU_BAD_ARG_COUNT
56 if [[ $# -eq 2 ]]; then # only num1 is given
57 result="exactly $2 args needed, $1 given"
58 [[ $1 -ne $2 ]] && return
63 result="need at least $2 args, $1 given"
64 [[ $1 -lt $2 ]] && return
65 result="need at most $3 args, $1 given"
66 [[ $1 -gt $3 ]] && return
69 export -f gsu_check_arg_count
75 export -f gsu_short_msg
79 gsu_short_msg "$_gsu_self: $1"
85 gsu_short_msg "$_gsu_self $(date): $1"
87 export -f gsu_date_msg
93 local txt="*** $_gsu_self --"
94 if test -z "$gsu_banner_txt"; then
95 txt="$txt set \$gsu_banner_txt to customize this message"
97 txt="$txt $gsu_banner_txt"
99 gsu_short_msg "$txt ***"
101 export -f _gsu_banner_msg
105 local txt="$result" err
107 gsu_is_a_number "$ret"
108 if test $ret -lt 0; then
109 gsu_msg "unknown error ($ret:$txt)"
112 if test $result -ge 0; then
113 gsu_msg "unknown error ($result:$txt)"
117 if test -n "$txt"; then
118 txt="$txt: ${gsu_error_txt[$err]}"
120 txt="${gsu_error_txt[$err]}"
124 export -f gsu_err_msg
128 gsu_short_msg "Usage: $_gsu_self command [options]"
132 _gsu_available_commands()
134 result="$( (printf "help\nman\nprefs\n"; grep "^com_[a-z_]\+()" $0) \
135 | sed -e 's/^com_//' -e 's/()//' \
140 export -f _gsu_available_commands
142 _gsu_print_available_commands()
145 gsu_short_msg "Available commands:"
146 for i in $gsu_cmds; do
148 count=$(($count + 1))
149 if test $(($count % 4)) -eq 0; then
153 if test ${#i} -lt 8; then
161 export -f _gsu_print_available_commands
163 export gsu_prefs_txt="
164 Print the current preferences.
168 Print out a list of all cmt config variables, together with their current value
169 and the default value."
174 for ((i=0; i < ${#gsu_options[@]}; i++)); do
175 local name= option_type= default_value= required=
176 local description= help_text=
177 eval "${gsu_options[$i]}"
178 eval val='"$'${gsu_config_var_prefix}_$name'"'
187 printf " $option_type: $description"
188 if [[ "$required" != "yes" && "$required" != "true" ]]; then
189 printf " [$default_value]"
192 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
194 [[ "$val" == "$default_value" ]] && printf " # default"
207 local equal_signs="=================================================="
208 local minus_signs="--------------------------------------------------"
211 echo "$_gsu_self (_${gsu_banner_txt}_) manual"
212 echo "${equal_signs:0:${#_gsu_self} + ${#gsu_banner_txt} + 16}"
215 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
218 echo "$_gsu_self usage"
219 echo "${minus_signs:0:${#_gsu_self} + 6}"
222 echo "Each command has its own set of options as described below."
226 echo "Available commands:"
228 _gsu_available_commands
229 for com in $result; do
231 if test $num -lt 4; then
234 echo "${minus_signs:0:$num}"
236 echo "${minus_signs:0:$num}"
244 export gsu_help_txt="
247 Usage: help [command]
249 Without arguments, print the list of available commands. Otherwise,
250 print the help text for the given command."
255 if test -z "$1"; then
259 (printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
260 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
261 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
263 grep -A 2 "^com_\([a-zA-Z_0-9]\+\)()" $0) \
265 | sed -e '/^com_\([a-zA-Z_0-9]\+\)()/bs' \
266 -e 'H;$!d;x;s/\n//g;b' \
268 -e 'x;s/\n//g;${p;x;}' \
269 | sed -e 's/^com_\([a-zA-Z_0-9]\+\)()#*/\1\t/' \
273 if test ${#a} -lt 8; then
279 echo "Try $_gsu_self help <command> for info on <command>."
283 if test "$1" = "help"; then
288 if test "$1" = "man"; then
293 if test "$1" = "prefs"; then
294 echo "$gsu_prefs_txt"
299 if grep -q "^com_$1()" $0; then
300 sed -e "1,/com_$1()/d" -e '/^{/,$d' -e 's/^## *//' $0
303 _gsu_print_available_commands
305 ret=-$E_GSU_BAD_COMMAND
309 # internal gsu function that syntactically checks the gsu_options array
310 # for errors and parses the config file.
313 local i conf="${gsu_config_file:=$HOME/.$gsu_name.rc}" val
315 for ((i=0; i < ${#gsu_options[@]}; i++)); do
316 eval "${gsu_options[$i]}"
317 eval val='"'\$$name'"'
318 eval orig_${gsu_config_var_prefix}_$name='"'${val}'"'
321 [[ -r "$conf" ]] && source "$conf"
323 for ((i=0; i < ${#gsu_options[@]}; i++)); do
324 local name= option_type= default_value= required=
325 local description= help_text=
328 eval "${gsu_options[$i]}"
331 # Check name. It must be non-empty and consist of [a-zA-Z_0-9]
332 # only. Moreover it must not start with [a-zA-Z].
334 ret=-$E_GSU_BAD_CONFIG_VAR
335 result="name: '$name'"
336 # bash's =~ works only for 3.2 and newer, so use grep
337 echo "$name" | grep '^[a-zA-Z][a-zA-Z_0123456789]*$' &> /dev/null;
338 [[ $? -ne 0 ]] && return
340 eval orig_val='"'\$orig_${gsu_config_var_prefix}_$name'"'
341 if [[ -z "$orig_val" ]]; then
342 eval val='"'\$$name'"'
348 ret=-$E_GSU_NEED_VALUE
350 [[ -z "$val" ]] && return
356 result="required: $required, name: $name, val: $val"
360 eval ${gsu_config_var_prefix}_$name='"'${val:=$default_value}'"'
361 # Check option type. ATM, only num and string are supported
362 # Other types may be added without breaking compatibility
363 case "$option_type" in
367 gsu_is_a_number "$val"
368 [[ $ret -lt 0 ]] && return
371 ret=-$E_GSU_BAD_OPTION_TYPE
372 result="$name/$option_type"
378 export -f _gsu_check_options
384 _gsu_self="$(basename $0)"
385 gsu_name="${gsu_name:=$_gsu_self}"
386 gsu_config_var_prefix="${gsu_config_var_prefix:=$gsu_name}"
389 if [[ "$ret" -lt 0 ]]; then
390 if [[ "$1" != "help" && "$1" != "man" ]]; then
395 _gsu_available_commands
397 if test $# -eq 0; then
399 _gsu_print_available_commands
404 for i in $gsu_cmds; do
405 if test "$arg" = "$i"; then
407 if test $ret -lt 0; then
414 ret=-$E_GSU_BAD_COMMAND
417 _gsu_print_available_commands
422 # TODO: gsu_strerror: get error string