2 # (C) 2006-2011 Andre Noll
4 if [[ "$(type -t _gsu_setup)" != "function" ]]; then
5 gsu_dir=${gsu_dir:-${BASH_SOURCE[0]%/*}}
6 . $gsu_dir/common || exit 1
12 gsu_short_msg "# Usage: $gsu_name command [options]"
15 # Return an extended regular expression to match against $0.
17 # When called without argument, the expression matches all lines which define a
20 # If an argument is given, the returned expression matches only the subcommand
21 # passed as $1. This is useful to tell if a string is a valid subcommand.
23 # Regardless of whether an argument is given, the returned expression contains
24 # exactly one parenthesized subexpression for matching the command name.
25 _gsu_get_command_regex()
27 local cmd="${1:-[-a-zA-Z_0-9]+}"
28 result="^com_($cmd)\(\)"
31 _gsu_available_commands()
35 _gsu_get_command_regex
38 printf "help\nman\nprefs\ncomplete\n"
40 # if line matches, isolate command name
43 # if there is a match, (print it and) start next cycle
49 } | sort | tr '\n' ' ')"
52 _gsu_print_available_commands()
55 gsu_short_msg "Available commands:"
56 for i in $gsu_cmds; do
59 if test $(($count % 4)) -eq 0; then
63 if test ${#i} -lt 8; then
72 gsu_complete_options()
74 local opts="$1" cword="$2" cur opt
79 cur="${words[$cword]}"
81 [[ ! "$cur" == -* ]] && return
84 for ((i=0; i < ${#opts}; i++)); do
86 [[ "$opt" == ":" ]] && continue
92 export gsu_prefs_txt="
93 Print the current preferences.
97 If -e is given, the config file is opened with the default editor. Without
98 options, the command prints out a list of all cmt config variables, together
99 with their current value and the default value."
102 local i conf="${gsu_config_file:=${HOME:-}/.$gsu_name.rc}"
106 (($ret < 0)) && return
107 gsu_check_arg_count $# 0 0
108 (($ret < 0)) && return
110 if [[ "$o_e" == "true" ]]; then
114 (($? != 0)) && return
116 result="${EDITOR:-vi}"
118 (($? != 0)) && return
123 for ((i=0; i < ${#gsu_options[@]}; i++)); do
124 local name= option_type= default_value= required=
125 local description= help_text=
126 eval "${gsu_options[$i]}"
127 eval val='"${'${gsu_config_var_prefix}_$name:-'}"'
136 printf " $option_type: $description"
137 if [[ "$required" != "yes" && "$required" != "true" ]]; then
138 printf " [$default_value]"
141 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
143 [[ "$val" == "$default_value" ]] && printf " # default"
150 gsu_complete_options "e" "$@"
160 local equal_signs="=================================================="
161 local minus_signs="--------------------------------------------------"
164 echo "$gsu_name (_${gsu_banner_txt}_) manual"
165 echo "${equal_signs:0:${#gsu_name} + ${#gsu_banner_txt} + 16}"
168 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
171 echo "$gsu_name usage"
172 echo "${minus_signs:0:${#gsu_name} + 6}"
175 echo "Each command has its own set of options as described below."
179 echo "Available commands:"
181 _gsu_available_commands
182 for com in $result; do
184 (($num < 4)) && num=4
185 echo "${minus_signs:0:$num}"
187 echo "${minus_signs:0:$num}"
194 export gsu_help_txt="
197 Usage: help [command]
199 Without arguments, print the list of available commands. Otherwise,
200 print the help text for the given command."
202 export gsu_complete_txt="
203 Command line completion.
205 Usage: complete [<cword> <word>...]
207 When executed without argument the command writes bash code to
208 stdout. This code is suitable to be evaled from .bashrc to enable
211 If at least one argument is given, all possible completions are
212 written to stdout. This can be used from the completion function of
218 local a b ere tab=' '
220 _gsu_get_command_regex
224 gsu_short_msg "### $gsu_name -- $gsu_banner_txt ###"
227 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
228 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
229 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
230 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
232 } | grep -v -- '--' \
233 | sed -En "/$ere/"'!d
234 # remove everything but the command name
235 s/^com_(.*)\(\).*/\1/
237 # append tab after short commands (less than 8 chars)
238 s/^(.{1,7})$/\1'"$tab"'/g
240 # remove next line (should contain only ## anyway)
244 # append next line, removing leading ##
248 # replace newline by tab
251 # and print the sucker
254 echo "# Try $gsu_name help <command> for info on <command>."
258 if test "$1" = "help"; then
263 if test "$1" = "man"; then
268 if test "$1" = "prefs"; then
269 echo "$gsu_prefs_txt"
273 if test "$1" = "complete"; then
274 echo "$gsu_complete_txt"
279 _gsu_get_command_regex "$1"
281 if ! grep -Eq "$ere" $0; then
282 _gsu_print_available_commands
284 ret=-$E_GSU_BAD_COMMAND
288 # only consider lines in the comment of the function
294 # if it did start with ##, jump to label p and print it
297 # otherwise, move on to next line
309 _gsu_available_commands
313 # Wrapper for the bash getopts builtin.
315 # Aborts on programming errors such as missing or invalid option string. On
316 # success $result contains shell code that can be eval'ed. For each defined
317 # option x, the local variable o_x will be created when calling eval "$result".
318 # o_x contains true/false for options without argument and either the emtpy
319 # string or the given argument for options that take an argument.
322 # gsu_getopts abc:x:y
324 # (($ret < 0)) && return
326 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
327 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
330 local i c tab=' ' cr='
333 gsu_check_arg_count $# 1 1
334 if (($ret < 0)); then
340 result="invalid optstring $1"
341 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
346 for ((i=0; i < ${#1}; i++)); do
352 result="invalid character $c in optstring"
357 result="local _gsu_getopts_opt"
358 for ((i=0; i < ${#1}; i++)); do
360 c2=${1:$(($i + 1)):1}
362 if [[ "$c2" = ":" ]]; then
370 while getopts $1 _gsu_getopts_opt \"\$@\"; do
371 case \"\$_gsu_getopts_opt\" in
373 for ((i=0; i < ${#1}; i++)); do
375 c2=${1:$(($i + 1)):1}
376 result+="$tab$tab$c1) o_$c1="
377 if [[ "$c2" = ":" ]]; then
378 result+="\"\$OPTARG\""
388 result=\"invalid option given\"
393 shift \$((\$OPTIND - 1))
405 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
408 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
409 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
416 gsu_is_a_number "$cword"
417 (($ret < 0)) && return
418 if (($cword <= 1)); then
419 _gsu_available_commands
427 ret=$GSU_SUCCESS # It's not an error if no completer was defined
428 [[ "$(type -t complete_$cmd)" != "function" ]] && return
429 complete_$cmd "$cword" "${words[@]}"
430 # ignore errors, they would only clutter the completion output
434 # Find out if the current word is a parameter for an option.
436 # $1: usual getopts option string.
437 # $2: The current word number.
438 # $3..: All words of the current command line.
440 # return: If yes, $result contains the letter of the option for which the
441 # current word is a parameter. Otherwise, $result is empty.
443 gsu_cword_is_option_parameter()
445 local opts="$1" cword="$2" prev i n
449 (($cword == 0)) && return
450 ((${#opts} < 2)) && return
454 prev="${words[$(($cword - 1))]}"
455 [[ ! "$prev" == -* ]] && return
458 for ((i=0; i <= $n; i++)); do
460 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
462 [[ "$prev" != "-$opt" ]] && continue
469 # Get the word number on which the cursor is, not counting options.
471 # This is useful for completing commands whose possible completions depend
472 # on the word number, for example mount.
474 # $1: Getopt option string.
475 # $2: The current word number.
476 # $3..: All words of the current command line.
478 # return: If the current word is an option, or a parameter to an option,
479 # this function sets $result to -1. Otherwise, the number of the non-option
480 # is returned in $result.
482 gsu_get_unnamed_arg_num()
484 local opts="$1" cword="$2" prev cur
490 cur="${words[$cword]}"
491 prev="${words[$(($cword - 1))]}"
493 [[ "$cur" == -* ]] && return
494 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
496 for ((i=1; i <= $cword; i++)); do
497 prev="${words[$(($i - 1))]}"
499 [[ "$cur" == -* ]] && continue
500 if [[ "$prev" == -* ]]; then
502 [[ "$opts" != *$opt:* ]] && let n++
510 # Entry point for all gsu-based scripts.
512 # The startup part of the application script should source this file to load
513 # the functions defined here, and then call gsu(). Functions starting with com_
514 # are automatically recognized as subcommands.
522 # gsu_dir=${gsu_dir:-/system/location/where/gsu/is/installed}
523 # . $gsu_dir/subcommand || exit 1
528 _gsu_available_commands
532 _gsu_print_available_commands
537 # check internal commands
538 if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
540 if (("$ret" < 0)); then
548 for i in $gsu_cmds; do
549 if test "$arg" = "$i"; then
551 if (("$ret" < 0)); then
559 ret=-$E_GSU_BAD_COMMAND
562 _gsu_print_available_commands
566 # Check number of arguments.
568 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
570 # Check that <num_given> is between <num1> and <num2> inclusively.
571 # If only <num1> ist given, num2 is assumed to be infinity.
574 # 0 0 no argument allowed
575 # 1 1 exactly one argument required
576 # 0 2 at most two arguments admissible
577 # 2 at least two arguments reqired
579 gsu_check_arg_count()
581 ret=-$E_GSU_BAD_ARG_COUNT
582 if (($# == 2)); then # only num1 is given
583 result="at least $2 args required, $1 given"
584 (($1 < $2)) && return
588 # num1 and num2 given
589 result="need at least $2 args, $1 given"
590 (($1 < $2)) && return
591 result="need at most $3 args, $1 given"
592 (($1 > $3)) && return