2 # (C) 2006-2011 Andre Noll
4 if [[ $(type -t gsu_is_a_number) != "function" ]]; then
5 GSU_DIR=${GSU_DIR:=${HOME-}/.gsu}
6 . $GSU_DIR/common || exit 1
11 gsu_short_msg "# Usage: $_gsu_self command [options]"
14 # Return an extended regular expression to match against $0.
16 # When called without argument, the expression matches all lines which define a
19 # If an argument is given, the returned expression matches only the subcommand
20 # passed as $1. This is useful to tell if a string is a valid subcommand.
22 # Regardless of whether an argument is given, the returned expression contains
23 # exactly one parenthesized subexpression for matching the command name.
24 _gsu_get_command_regex()
26 local cmd="${1:-[-a-zA-Z_0-9]+}"
27 result="^com_($cmd)\(\)"
30 _gsu_available_commands()
34 _gsu_get_command_regex
37 printf "help\nman\nprefs\ncomplete\n"
39 # if line matches, isolate command name
42 # if there is a match, (print it and) start next cycle
48 } | sort | tr '\n' ' ')"
51 _gsu_print_available_commands()
56 printf 'Available commands:\n'
57 for cmd in $gsu_cmds; do
60 if (($count % 4)); then
62 ((${#cmd} < 8)) && printf '\t'
70 gsu_complete_options()
72 local opts="$1" cword="$2" cur opt
77 cur="${words[$cword]}"
79 [[ ! "$cur" == -* ]] && return
82 for ((i=0; i < ${#opts}; i++)); do
84 [[ "$opt" == ":" ]] && continue
90 export gsu_prefs_txt="
91 Print the current preferences.
95 If -e is given, the config file is opened with the default editor. Without
96 options, the command prints out a list of all cmt config variables, together
97 with their current value and the default value."
100 local i conf="${gsu_config_file:=${HOME:-}/.$gsu_name.rc}"
104 (($ret < 0)) && return
105 gsu_check_arg_count $# 0 0
106 (($ret < 0)) && return
108 if [[ "$o_e" == "true" ]]; then
112 [[ $? -ne 0 ]] && return
114 result="${EDITOR:-vi}"
116 [[ $? -ne 0 ]] && return
121 for ((i=0; i < ${#gsu_options[@]}; i++)); do
122 local name= option_type= default_value= required=
123 local description= help_text=
124 eval "${gsu_options[$i]}"
125 eval val='"${'${gsu_config_var_prefix}_$name:-'}"'
134 printf " $option_type: $description"
135 if [[ "$required" != "yes" && "$required" != "true" ]]; then
136 printf " [$default_value]"
139 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
141 [[ "$val" == "$default_value" ]] && printf " # default"
148 gsu_complete_options "e" "$@"
158 local equal_signs="=================================================="
159 local minus_signs="--------------------------------------------------"
162 echo "$_gsu_self (_${gsu_banner_txt}_) manual"
163 echo "${equal_signs:0:${#_gsu_self} + ${#gsu_banner_txt} + 16}"
166 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
169 echo "$_gsu_self usage"
170 echo "${minus_signs:0:${#_gsu_self} + 6}"
173 echo "Each command has its own set of options as described below."
177 echo "Available commands:"
179 _gsu_available_commands
180 for com in $result; do
182 if test $num -lt 4; then
185 echo "${minus_signs:0:$num}"
187 echo "${minus_signs:0:$num}"
196 gsu_short_msg "### $_gsu_self -- ###"
199 export gsu_help_txt="
202 Usage: help [command]
204 Without arguments, print the list of available commands. Otherwise,
205 print the help text for the given command."
207 export gsu_complete_txt="
208 Command line completion.
210 Usage: complete [<cword> <word>...]
212 When executed without argument the command writes bash code to
213 stdout. This code is suitable to be evaled from .bashrc to enable
216 If at least one argument is given, all possible completions are
217 written to stdout. This can be used from the completion function of
223 local a b ere tab=' '
225 _gsu_get_command_regex
232 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
233 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
234 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
235 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
237 } | grep -v -- '--' \
238 | sed -En "/$ere/"'!d
239 # remove everything but the command name
240 s/^com_(.*)\(\).*/\1/
242 # append tab after short commands (less than 8 chars)
243 s/^(.{1,7})$/\1'"$tab"'/g
245 # remove next line (should contain only ## anyway)
249 # append next line, removing leading ##
253 # replace newline by tab
256 # and print the sucker
259 echo "# Try $_gsu_self help <command> for info on <command>."
263 if test "$1" = "help"; then
268 if test "$1" = "man"; then
273 if test "$1" = "prefs"; then
274 echo "$gsu_prefs_txt"
278 if test "$1" = "complete"; then
279 echo "$gsu_complete_txt"
284 _gsu_get_command_regex "$1"
286 if ! grep -Eq "$ere" $0; then
287 _gsu_print_available_commands
289 ret=-$E_GSU_BAD_COMMAND
293 # only consider lines in the comment of the function
299 # if it did start with ##, jump to label p and print it
302 # otherwise, move on to next line
314 _gsu_available_commands
318 # Wrapper for the bash getopts builtin.
320 # Aborts on programming errors such as missing or invalid option string. On
321 # success $result contains shell code that can be eval'ed. For each defined
322 # option x, the local variable o_x will be created when calling eval "$result".
323 # o_x contains true/false for options without argument and either the emtpy
324 # string or the given argument for options that take an argument.
327 # gsu_getopts abc:x:y
329 # (($ret < 0)) && return
331 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
332 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
335 local i c tab=' ' cr='
338 gsu_check_arg_count $# 1 1
339 if [[ $ret -lt 0 ]]; then
345 result="invalid optstring $1"
346 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
351 for ((i=0; i < ${#1}; i++)); do
357 result="invalid character $c in optstring"
362 result="local _gsu_getopts_opt"
363 for ((i=0; i < ${#1}; i++)); do
365 c2=${1:$(($i + 1)):1}
367 if [[ "$c2" = ":" ]]; then
375 while getopts $1 _gsu_getopts_opt \"\$@\"; do
376 case \"\$_gsu_getopts_opt\" in
378 for ((i=0; i < ${#1}; i++)); do
380 c2=${1:$(($i + 1)):1}
381 result+="$tab$tab$c1) o_$c1="
382 if [[ "$c2" = ":" ]]; then
383 result+="\"\$OPTARG\""
393 result=\"invalid option given\"
398 shift \$((\$OPTIND - 1))
410 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
413 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
414 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
421 gsu_is_a_number "$cword"
422 (($ret < 0)) && return
423 if (($cword <= 1)); then
424 _gsu_available_commands
432 ret=$GSU_SUCCESS # It's not an error if no completer was defined
433 [[ "$(type -t complete_$cmd)" != "function" ]] && return
434 complete_$cmd "$cword" "${words[@]}"
435 # ignore errors, they would only clutter the completion output
439 # Find out if the current word is a parameter for an option.
441 # $1: usual getopts option string.
442 # $2: The current word number.
443 # $3..: All words of the current command line.
445 # return: If yes, $result contains the letter of the option for which the
446 # current word is a parameter. Otherwise, $result is empty.
448 gsu_cword_is_option_parameter()
450 local opts="$1" cword="$2" prev i n
454 (($cword == 0)) && return
455 ((${#opts} < 2)) && return
459 prev="${words[$(($cword - 1))]}"
460 [[ ! "$prev" == -* ]] && return
463 for ((i=0; i <= $n; i++)); do
465 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
467 [[ "$prev" != "-$opt" ]] && continue
474 # Get the word number on which the cursor is, not counting options.
476 # This is useful for completing commands whose possible completions depend
477 # on the word number, for example mount.
479 # $1: Getopt option string.
480 # $2: The current word number.
481 # $3..: All words of the current command line.
483 # return: If the current word is an option, or a parameter to an option,
484 # this function sets $result to -1. Otherwise, the number of the non-option
485 # is returned in $result.
487 gsu_get_unnamed_arg_num()
489 local opts="$1" cword="$2" prev cur
495 cur="${words[$cword]}"
496 prev="${words[$(($cword - 1))]}"
498 [[ "$cur" == -* ]] && return
499 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
501 for ((i=1; i <= $cword; i++)); do
502 prev="${words[$(($i - 1))]}"
504 [[ "$cur" == -* ]] && continue
505 if [[ "$prev" == -* ]]; then
507 [[ "$opts" != *$opt:* ]] && let n++
515 # Entry point for all gsu-based scripts.
517 # The startup part of the application script should source this file to load
518 # the functions defined here, and then call gsu(). Functions starting with com_
519 # are automatically recognized as subcommands.
527 # gsu_dir=${gsu_dir:-/system/location/where/gsu/is/installed}
528 # . $gsu_dir/subcommand || exit 1
534 _gsu_available_commands
536 if test $# -eq 0; then
538 _gsu_print_available_commands
543 # check internal commands
544 if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
546 if [[ "$ret" -lt 0 ]]; then
554 for i in $gsu_cmds; do
555 if test "$arg" = "$i"; then
557 if [[ "$ret" -lt 0 ]]; then
565 ret=-$E_GSU_BAD_COMMAND
568 _gsu_print_available_commands
572 # Check number of arguments.
574 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
576 # Check that <num_given> is between <num1> and <num2> inclusively.
577 # If only <num1> ist given, num2 is assumed to be infinity.
580 # 0 0 no argument allowed
581 # 1 1 exactly one argument required
582 # 0 2 at most two arguments admissible
583 # 2 at least two arguments reqired
585 gsu_check_arg_count()
587 ret=-$E_GSU_BAD_ARG_COUNT
588 if [[ $# -eq 2 ]]; then # only num1 is given
589 result="at least $2 args required, $1 given"
590 [[ $1 -lt $2 ]] && return
594 # num1 and num2 given
595 result="need at least $2 args, $1 given"
596 [[ $1 -lt $2 ]] && return
597 result="need at most $3 args, $1 given"
598 [[ $1 -gt $3 ]] && return