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()
54 gsu_short_msg "Available commands:"
55 for i in $gsu_cmds; do
58 if test $(($count % 4)) -eq 0; then
62 if test ${#i} -lt 8; then
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 [[ $? -ne 0 ]] && return
115 result="${EDITOR:-vi}"
117 [[ $? -ne 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_self (_${gsu_banner_txt}_) manual"
164 echo "${equal_signs:0:${#_gsu_self} + ${#gsu_banner_txt} + 16}"
167 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
170 echo "$_gsu_self usage"
171 echo "${minus_signs:0:${#_gsu_self} + 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 if test $num -lt 4; then
186 echo "${minus_signs:0:$num}"
188 echo "${minus_signs:0:$num}"
197 gsu_short_msg "### $_gsu_self -- ###"
200 export gsu_help_txt="
203 Usage: help [command]
205 Without arguments, print the list of available commands. Otherwise,
206 print the help text for the given command."
208 export gsu_complete_txt="
209 Command line completion.
211 Usage: complete [<cword> <word>...]
213 When executed without argument the command writes bash code to
214 stdout. This code is suitable to be evaled from .bashrc to enable
217 If at least one argument is given, all possible completions are
218 written to stdout. This can be used from the completion function of
224 local a b ere tab=' '
226 _gsu_get_command_regex
233 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
234 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
235 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
236 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
238 } | grep -v -- '--' \
239 | sed -En "/$ere/"'!d
240 # remove everything but the command name
241 s/^com_(.*)\(\).*/\1/
243 # append tab after short commands (less than 8 chars)
244 s/^(.{1,7})$/\1'"$tab"'/g
246 # remove next line (should contain only ## anyway)
250 # append next line, removing leading ##
254 # replace newline by tab
257 # and print the sucker
260 echo "# Try $_gsu_self help <command> for info on <command>."
264 if test "$1" = "help"; then
269 if test "$1" = "man"; then
274 if test "$1" = "prefs"; then
275 echo "$gsu_prefs_txt"
279 if test "$1" = "complete"; then
280 echo "$gsu_complete_txt"
285 _gsu_get_command_regex "$1"
287 if ! grep -Eq "$ere" $0; then
288 _gsu_print_available_commands
290 ret=-$E_GSU_BAD_COMMAND
294 # only consider lines in the comment of the function
300 # if it did start with ##, jump to label p and print it
303 # otherwise, move on to next line
315 _gsu_available_commands
319 # Wrapper for the bash getopts builtin.
321 # Aborts on programming errors such as missing or invalid option string. On
322 # success $result contains shell code that can be eval'ed. For each defined
323 # option x, the local variable o_x will be created when calling eval "$result".
324 # o_x contains true/false for options without argument and either the emtpy
325 # string or the given argument for options that take an argument.
328 # gsu_getopts abc:x:y
330 # (($ret < 0)) && return
332 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
333 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
336 local i c tab=' ' cr='
339 gsu_check_arg_count $# 1 1
340 if [[ $ret -lt 0 ]]; then
346 result="invalid optstring $1"
347 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
352 for ((i=0; i < ${#1}; i++)); do
358 result="invalid character $c in optstring"
363 result="local _gsu_getopts_opt"
364 for ((i=0; i < ${#1}; i++)); do
366 c2=${1:$(($i + 1)):1}
368 if [[ "$c2" = ":" ]]; then
376 while getopts $1 _gsu_getopts_opt \"\$@\"; do
377 case \"\$_gsu_getopts_opt\" in
379 for ((i=0; i < ${#1}; i++)); do
381 c2=${1:$(($i + 1)):1}
382 result+="$tab$tab$c1) o_$c1="
383 if [[ "$c2" = ":" ]]; then
384 result+="\"\$OPTARG\""
394 result=\"invalid option given\"
399 shift \$((\$OPTIND - 1))
411 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
414 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
415 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
422 gsu_is_a_number "$cword"
423 (($ret < 0)) && return
424 if (($cword <= 1)); then
425 _gsu_available_commands
433 ret=$GSU_SUCCESS # It's not an error if no completer was defined
434 [[ "$(type -t complete_$cmd)" != "function" ]] && return
435 complete_$cmd "$cword" "${words[@]}"
436 # ignore errors, they would only clutter the completion output
440 # Find out if the current word is a parameter for an option.
442 # $1: usual getopts option string.
443 # $2: The current word number.
444 # $3..: All words of the current command line.
446 # return: If yes, $result contains the letter of the option for which the
447 # current word is a parameter. Otherwise, $result is empty.
449 gsu_cword_is_option_parameter()
451 local opts="$1" cword="$2" prev i n
455 (($cword == 0)) && return
456 ((${#opts} < 2)) && return
460 prev="${words[$(($cword - 1))]}"
461 [[ ! "$prev" == -* ]] && return
464 for ((i=0; i <= $n; i++)); do
466 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
468 [[ "$prev" != "-$opt" ]] && continue
475 # Get the word number on which the cursor is, not counting options.
477 # This is useful for completing commands whose possible completions depend
478 # on the word number, for example mount.
480 # $1: Getopt option string.
481 # $2: The current word number.
482 # $3..: All words of the current command line.
484 # return: If the current word is an option, or a parameter to an option,
485 # this function sets $result to -1. Otherwise, the number of the non-option
486 # is returned in $result.
488 gsu_get_unnamed_arg_num()
490 local opts="$1" cword="$2" prev cur
496 cur="${words[$cword]}"
497 prev="${words[$(($cword - 1))]}"
499 [[ "$cur" == -* ]] && return
500 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
502 for ((i=1; i <= $cword; i++)); do
503 prev="${words[$(($i - 1))]}"
505 [[ "$cur" == -* ]] && continue
506 if [[ "$prev" == -* ]]; then
508 [[ "$opts" != *$opt:* ]] && let n++
516 # Entry point for all gsu-based scripts.
518 # The startup part of the application script should source this file to load
519 # the functions defined here, and then call gsu(). Functions starting with com_
520 # are automatically recognized as subcommands.
528 # gsu_dir=${gsu_dir:-/system/location/where/gsu/is/installed}
529 # . $gsu_dir/subcommand || exit 1
535 _gsu_available_commands
537 if test $# -eq 0; then
539 _gsu_print_available_commands
544 # check internal commands
545 if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
547 if [[ "$ret" -lt 0 ]]; then
555 for i in $gsu_cmds; do
556 if test "$arg" = "$i"; then
558 if [[ "$ret" -lt 0 ]]; then
566 ret=-$E_GSU_BAD_COMMAND
569 _gsu_print_available_commands
573 # Check number of arguments.
575 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
577 # Check that <num_given> is between <num1> and <num2> inclusively.
578 # If only <num1> ist given, num2 is assumed to be infinity.
581 # 0 0 no argument allowed
582 # 1 1 exactly one argument required
583 # 0 2 at most two arguments admissible
584 # 2 at least two arguments reqired
586 gsu_check_arg_count()
588 ret=-$E_GSU_BAD_ARG_COUNT
589 if [[ $# -eq 2 ]]; then # only num1 is given
590 result="at least $2 args required, $1 given"
591 [[ $1 -lt $2 ]] && return
595 # num1 and num2 given
596 result="need at least $2 args, $1 given"
597 [[ $1 -lt $2 ]] && return
598 result="need at most $3 args, $1 given"
599 [[ $1 -gt $3 ]] && return