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()
57 printf 'Available commands:\n'
58 for cmd in $gsu_cmds; do
61 if (($count % 4)); then
63 ((${#cmd} < 8)) && printf '\t'
71 gsu_complete_options()
73 local opts="$1" cword="$2" cur opt
78 cur="${words[$cword]}"
80 [[ ! "$cur" == -* ]] && return
83 for ((i=0; i < ${#opts}; i++)); do
85 [[ "$opt" == ":" ]] && continue
91 export gsu_prefs_txt="
92 Print the current preferences.
96 If -e is given, the config file is opened with the default editor. Without
97 options, the command prints out a list of all cmt config variables, together
98 with their current value and the default value."
101 local i conf="${gsu_config_file:=${HOME:-}/.$gsu_name.rc}"
105 (($ret < 0)) && return
106 gsu_check_arg_count $# 0 0
107 (($ret < 0)) && return
109 if [[ "$o_e" == "true" ]]; then
113 (($? != 0)) && return
115 result="${EDITOR:-vi}"
117 (($? != 0)) && return
122 for ((i=0; i < ${#gsu_options[@]}; i++)); do
123 local name= option_type= default_value= required=
124 local description= help_text=
125 eval "${gsu_options[$i]}"
126 eval val='"${'${gsu_config_var_prefix}_$name:-'}"'
135 printf " $option_type: $description"
136 if [[ "$required" != "yes" && "$required" != "true" ]]; then
137 printf " [$default_value]"
140 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
142 [[ "$val" == "$default_value" ]] && printf " # default"
149 gsu_complete_options "e" "$@"
159 local equal_signs="=================================================="
160 local minus_signs="--------------------------------------------------"
163 echo "$gsu_name (_${gsu_banner_txt}_) manual"
164 echo "${equal_signs:0:${#gsu_name} + ${#gsu_banner_txt} + 16}"
167 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
170 echo "$gsu_name usage"
171 echo "${minus_signs:0:${#gsu_name} + 6}"
174 echo "Each command has its own set of options as described below."
178 echo "Available commands:"
180 _gsu_available_commands
181 for com in $result; do
183 (($num < 4)) && num=4
184 echo "${minus_signs:0:$num}"
186 echo "${minus_signs:0:$num}"
193 export gsu_help_txt="
196 Usage: help [command]
198 Without arguments, print the list of available commands. Otherwise,
199 print the help text for the given command."
201 export gsu_complete_txt="
202 Command line completion.
204 Usage: complete [<cword> <word>...]
206 When executed without argument the command writes bash code to
207 stdout. This code is suitable to be evaled from .bashrc to enable
210 If at least one argument is given, all possible completions are
211 written to stdout. This can be used from the completion function of
217 local a b ere tab=' '
219 _gsu_get_command_regex
223 gsu_short_msg "### $gsu_name -- $gsu_banner_txt ###"
226 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
227 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
228 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
229 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
231 } | grep -v -- '--' \
232 | sed -En "/$ere/"'!d
233 # remove everything but the command name
234 s/^com_(.*)\(\).*/\1/
236 # append tab after short commands (less than 8 chars)
237 s/^(.{1,7})$/\1'"$tab"'/g
239 # remove next line (should contain only ## anyway)
243 # append next line, removing leading ##
247 # replace newline by tab
250 # and print the sucker
253 echo "# Try $gsu_name help <command> for info on <command>."
257 if test "$1" = "help"; then
262 if test "$1" = "man"; then
267 if test "$1" = "prefs"; then
268 echo "$gsu_prefs_txt"
272 if test "$1" = "complete"; then
273 echo "$gsu_complete_txt"
278 _gsu_get_command_regex "$1"
280 if ! grep -Eq "$ere" $0; then
281 _gsu_print_available_commands
283 ret=-$E_GSU_BAD_COMMAND
287 # only consider lines in the comment of the function
293 # if it did start with ##, jump to label p and print it
296 # otherwise, move on to next line
308 _gsu_available_commands
312 # Wrapper for the bash getopts builtin.
314 # Aborts on programming errors such as missing or invalid option string. On
315 # success $result contains shell code that can be eval'ed. For each defined
316 # option x, the local variable o_x will be created when calling eval "$result".
317 # o_x contains true/false for options without argument and either the emtpy
318 # string or the given argument for options that take an argument.
321 # gsu_getopts abc:x:y
323 # (($ret < 0)) && return
325 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
326 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
329 local i c tab=' ' cr='
332 gsu_check_arg_count $# 1 1
333 if (($ret < 0)); then
339 result="invalid optstring $1"
340 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
345 for ((i=0; i < ${#1}; i++)); do
351 result="invalid character $c in optstring"
356 result="local _gsu_getopts_opt"
357 for ((i=0; i < ${#1}; i++)); do
359 c2=${1:$(($i + 1)):1}
361 if [[ "$c2" = ":" ]]; then
369 while getopts $1 _gsu_getopts_opt \"\$@\"; do
370 case \"\$_gsu_getopts_opt\" in
372 for ((i=0; i < ${#1}; i++)); do
374 c2=${1:$(($i + 1)):1}
375 result+="$tab$tab$c1) o_$c1="
376 if [[ "$c2" = ":" ]]; then
377 result+="\"\$OPTARG\""
387 result=\"invalid option given\"
392 shift \$((\$OPTIND - 1))
404 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
407 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
408 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
415 gsu_is_a_number "$cword"
416 (($ret < 0)) && return
417 if (($cword <= 1)); then
418 _gsu_available_commands
426 ret=$GSU_SUCCESS # It's not an error if no completer was defined
427 [[ "$(type -t complete_$cmd)" != "function" ]] && return
428 complete_$cmd "$cword" "${words[@]}"
429 # ignore errors, they would only clutter the completion output
433 # Find out if the current word is a parameter for an option.
435 # $1: usual getopts option string.
436 # $2: The current word number.
437 # $3..: All words of the current command line.
439 # return: If yes, $result contains the letter of the option for which the
440 # current word is a parameter. Otherwise, $result is empty.
442 gsu_cword_is_option_parameter()
444 local opts="$1" cword="$2" prev i n
448 (($cword == 0)) && return
449 ((${#opts} < 2)) && return
453 prev="${words[$(($cword - 1))]}"
454 [[ ! "$prev" == -* ]] && return
457 for ((i=0; i <= $n; i++)); do
459 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
461 [[ "$prev" != "-$opt" ]] && continue
468 # Get the word number on which the cursor is, not counting options.
470 # This is useful for completing commands whose possible completions depend
471 # on the word number, for example mount.
473 # $1: Getopt option string.
474 # $2: The current word number.
475 # $3..: All words of the current command line.
477 # return: If the current word is an option, or a parameter to an option,
478 # this function sets $result to -1. Otherwise, the number of the non-option
479 # is returned in $result.
481 gsu_get_unnamed_arg_num()
483 local opts="$1" cword="$2" prev cur
489 cur="${words[$cword]}"
490 prev="${words[$(($cword - 1))]}"
492 [[ "$cur" == -* ]] && return
493 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
495 for ((i=1; i <= $cword; i++)); do
496 prev="${words[$(($i - 1))]}"
498 [[ "$cur" == -* ]] && continue
499 if [[ "$prev" == -* ]]; then
501 [[ "$opts" != *$opt:* ]] && let n++
509 # Entry point for all gsu-based scripts.
511 # The startup part of the application script should source this file to load
512 # the functions defined here, and then call gsu(). Functions starting with com_
513 # are automatically recognized as subcommands.
521 # gsu_dir=${gsu_dir:-/system/location/where/gsu/is/installed}
522 # . $gsu_dir/subcommand || exit 1
527 _gsu_available_commands
531 _gsu_print_available_commands
536 # check internal commands
537 if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
539 if (("$ret" < 0)); then
547 for i in $gsu_cmds; do
548 if test "$arg" = "$i"; then
550 if (("$ret" < 0)); then
558 ret=-$E_GSU_BAD_COMMAND
561 _gsu_print_available_commands
565 # Check number of arguments.
567 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
569 # Check that <num_given> is between <num1> and <num2> inclusively.
570 # If only <num1> ist given, num2 is assumed to be infinity.
573 # 0 0 no argument allowed
574 # 1 1 exactly one argument required
575 # 0 2 at most two arguments admissible
576 # 2 at least two arguments reqired
578 gsu_check_arg_count()
580 ret=-$E_GSU_BAD_ARG_COUNT
581 if (($# == 2)); then # only num1 is given
582 result="at least $2 args required, $1 given"
583 (($1 < $2)) && return
587 # num1 and num2 given
588 result="need at least $2 args, $1 given"
589 (($1 < $2)) && return
590 result="need at most $3 args, $1 given"
591 (($1 > $3)) && return