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 # Each line matching this is recognized as a subcommand. The name of the may be
15 # given as $1. In any case the subcommand is the first subexpression.
16 _gsu_get_command_regex()
18 local cmd="${1:-[-a-zA-Z_0-9]+}"
19 result="^com_($cmd)\(\)"
22 _gsu_available_commands()
26 _gsu_get_command_regex
29 printf "help\nman\nprefs\ncomplete\n"
31 # if line matches, isolate command name
34 # if there is a match, (print it and) start next cycle
40 } | sort | tr '\n' ' ')"
43 _gsu_print_available_commands()
46 gsu_short_msg "Available commands:"
47 for i in $gsu_cmds; do
50 if test $(($count % 4)) -eq 0; then
54 if test ${#i} -lt 8; then
63 gsu_complete_options()
65 local opts="$1" cword="$2" cur opt
70 cur="${words[$cword]}"
72 [[ ! "$cur" == -* ]] && return
75 for ((i=0; i < ${#opts}; i++)); do
77 [[ "$opt" == ":" ]] && continue
83 export gsu_prefs_txt="
84 Print the current preferences.
88 If -e is given, the config file is opened with the default editor. Without
89 options, the command prints out a list of all cmt config variables, together
90 with their current value and the default value."
93 local i conf="${gsu_config_file:=$HOME/.$gsu_name.rc}"
97 (($ret < 0)) && return
98 gsu_check_arg_count $# 0 0
99 (($ret < 0)) && return
101 if [[ "$o_e" == "true" ]]; then
105 [[ $? -ne 0 ]] && return
107 result="${EDITOR:-vi}"
109 [[ $? -ne 0 ]] && return
114 for ((i=0; i < ${#gsu_options[@]}; i++)); do
115 local name= option_type= default_value= required=
116 local description= help_text=
117 eval "${gsu_options[$i]}"
118 eval val='"${'${gsu_config_var_prefix}_$name:-'}"'
127 printf " $option_type: $description"
128 if [[ "$required" != "yes" && "$required" != "true" ]]; then
129 printf " [$default_value]"
132 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
134 [[ "$val" == "$default_value" ]] && printf " # default"
141 gsu_complete_options "e" "$@"
151 local equal_signs="=================================================="
152 local minus_signs="--------------------------------------------------"
155 echo "$_gsu_self (_${gsu_banner_txt}_) manual"
156 echo "${equal_signs:0:${#_gsu_self} + ${#gsu_banner_txt} + 16}"
159 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
162 echo "$_gsu_self usage"
163 echo "${minus_signs:0:${#_gsu_self} + 6}"
166 echo "Each command has its own set of options as described below."
170 echo "Available commands:"
172 _gsu_available_commands
173 for com in $result; do
175 if test $num -lt 4; then
178 echo "${minus_signs:0:$num}"
180 echo "${minus_signs:0:$num}"
189 gsu_short_msg "### $_gsu_self -- ###"
192 export gsu_help_txt="
195 Usage: help [command]
197 Without arguments, print the list of available commands. Otherwise,
198 print the help text for the given command."
200 export gsu_complete_txt="
201 Command line completion.
203 Usage: complete [<cword> <word>...]
205 When executed without argument the command writes bash code to
206 stdout. This code is suitable to be evaled from .bashrc to enable
209 If at least one argument is given, all possible completions are
210 written to stdout. This can be used from the completion function of
216 local a b ere tab=' '
218 _gsu_get_command_regex
225 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
226 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
227 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
228 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
230 } | grep -v -- '--' \
231 | sed -En "/$ere/"'!d
232 # remove everything but the command name
233 s/^com_(.*)\(\).*/\1/
235 # append tab after short commands (less than 8 chars)
236 s/^(.{1,7})$/\1'"$tab"'/g
238 # remove next line (should contain only ## anyway)
242 # append next line, removing leading ##
246 # replace newline by tab
249 # and print the sucker
252 echo "# Try $_gsu_self help <command> for info on <command>."
256 if test "$1" = "help"; then
261 if test "$1" = "man"; then
266 if test "$1" = "prefs"; then
267 echo "$gsu_prefs_txt"
271 if test "$1" = "complete"; then
272 echo "$gsu_complete_txt"
277 _gsu_get_command_regex "$1"
279 if ! grep -Eq "$ere" $0; then
280 _gsu_print_available_commands
282 ret=-$E_GSU_BAD_COMMAND
286 # only consider lines in the comment of the function
292 # if it did start with ##, jump to label p and print it
295 # otherwise, move on to next line
307 _gsu_available_commands
311 # Wrapper for the bash getopts builtin.
313 # Aborts on programming errors such as missing or invalid option string. On
314 # success $result contains shell code that can be eval'ed. For each defined
315 # option x, the local variable o_x will be created when calling eval "$result".
316 # o_x contains true/false for options without argument and either the emtpy
317 # string or the given argument for options that take an argument.
320 # gsu_getopts abc:x:y
322 # (($ret < 0)) && return
324 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
325 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
328 local i c tab=' ' cr='
331 gsu_check_arg_count $# 1 1
332 if [[ $ret -lt 0 ]]; then
338 result="invalid optstring $1"
339 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
344 for ((i=0; i < ${#1}; i++)); do
350 result="invalid character $c in optstring"
355 result="local _gsu_getopts_opt"
356 for ((i=0; i < ${#1}; i++)); do
358 c2=${1:$(($i + 1)):1}
360 if [[ "$c2" = ":" ]]; then
368 while getopts $1 _gsu_getopts_opt \"\$@\"; do
369 case \"\$_gsu_getopts_opt\" in
371 for ((i=0; i < ${#1}; i++)); do
373 c2=${1:$(($i + 1)):1}
374 result+="$tab$tab$c1) o_$c1="
375 if [[ "$c2" = ":" ]]; then
376 result+="\"\$OPTARG\""
386 result=\"invalid option given\"
391 shift \$((\$OPTIND - 1))
403 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
406 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
407 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
414 gsu_is_a_number "$cword"
415 (($ret < 0)) && return
416 if (($cword <= 1)); then
417 _gsu_available_commands
425 ret=$GSU_SUCCESS # It's not an error if no completer was defined
426 [[ "$(type -t complete_$cmd)" != "function" ]] && return
427 complete_$cmd "$cword" "${words[@]}"
428 # ignore errors, they would only clutter the completion output
432 # Find out if the current word is a parameter for an option.
434 # $1: usual getopts option string.
435 # $2: The current word number.
436 # $3..: All words of the current command line.
438 # return: If yes, $result contains the letter of the option for which the
439 # current word is a parameter. Otherwise, $result is empty.
441 gsu_cword_is_option_parameter()
443 local opts="$1" cword="$2" prev i n
447 (($cword == 0)) && return
448 ((${#opts} < 2)) && return
452 prev="${words[$(($cword - 1))]}"
453 [[ ! "$prev" == -* ]] && return
456 for ((i=0; i <= $n; i++)); do
458 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
460 [[ "$prev" != "-$opt" ]] && continue
467 # Get the word number on which the cursor is, not counting options.
469 # This is useful for completing commands whose possible completions depend
470 # on the word number, for example mount.
472 # $1: Getopt option string.
473 # $2: The current word number.
474 # $3..: All words of the current command line.
476 # return: If the current word is an option, or a parameter to an option,
477 # this function sets $result to -1. Otherwise, the number of the non-option
478 # is returned in $result.
480 gsu_get_unnamed_arg_num()
482 local opts="$1" cword="$2" prev cur
488 cur="${words[$cword]}"
489 prev="${words[$(($cword - 1))]}"
491 [[ "$cur" == -* ]] && return
492 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
494 for ((i=1; i <= $cword; i++)); do
495 prev="${words[$(($i - 1))]}"
497 [[ "$cur" == -* ]] && continue
498 if [[ "$prev" == -* ]]; then
500 [[ "$opts" != *$opt:* ]] && let n++
512 _gsu_available_commands
514 if test $# -eq 0; then
516 _gsu_print_available_commands
521 # check internal commands
522 if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
524 if [[ "$ret" -lt 0 ]]; then
532 for i in $gsu_cmds; do
533 if test "$arg" = "$i"; then
535 if [[ "$ret" -lt 0 ]]; then
543 ret=-$E_GSU_BAD_COMMAND
546 _gsu_print_available_commands
550 # Check number of arguments.
552 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
554 # Check that <num_given> is between <num1> and <num2> inclusively.
555 # If only <num1> ist given, num2 is assumed to be infinity.
558 # 0 0 no argument allowed
559 # 1 1 exactly one argument required
560 # 0 2 at most two arguments admissible
561 # 2 at least two arguments reqired
563 gsu_check_arg_count()
565 ret=-$E_GSU_BAD_ARG_COUNT
566 if [[ $# -eq 2 ]]; then # only num1 is given
567 result="at least $2 args required, $1 given"
568 [[ $1 -lt $2 ]] && return
572 # num1 and num2 given
573 result="need at least $2 args, $1 given"
574 [[ $1 -lt $2 ]] && return
575 result="need at most $3 args, $1 given"
576 [[ $1 -gt $3 ]] && return