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
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}"
95 if [[ "$1" = "-e" ]]; then
99 [[ $? -ne 0 ]] && return
101 result="${EDITOR:-vi}"
103 [[ $? -ne 0 ]] && return
108 for ((i=0; i < ${#gsu_options[@]}; i++)); do
109 local name= option_type= default_value= required=
110 local description= help_text=
111 eval "${gsu_options[$i]}"
112 eval val='"$'${gsu_config_var_prefix}_$name'"'
121 printf " $option_type: $description"
122 if [[ "$required" != "yes" && "$required" != "true" ]]; then
123 printf " [$default_value]"
126 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
128 [[ "$val" == "$default_value" ]] && printf " # default"
135 gsu_complete_options "e" "$@"
145 local equal_signs="=================================================="
146 local minus_signs="--------------------------------------------------"
149 echo "$_gsu_self (_${gsu_banner_txt}_) manual"
150 echo "${equal_signs:0:${#_gsu_self} + ${#gsu_banner_txt} + 16}"
153 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
156 echo "$_gsu_self usage"
157 echo "${minus_signs:0:${#_gsu_self} + 6}"
160 echo "Each command has its own set of options as described below."
164 echo "Available commands:"
166 _gsu_available_commands
167 for com in $result; do
169 if test $num -lt 4; then
172 echo "${minus_signs:0:$num}"
174 echo "${minus_signs:0:$num}"
183 local txt="### $_gsu_self --"
184 if test -z "$gsu_banner_txt"; then
185 txt="$txt set \$gsu_banner_txt to customize this message"
187 txt="$txt $gsu_banner_txt"
189 gsu_short_msg "$txt ###"
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 In the first form, the command prints all possible completions to stdout.
206 This can be used from the completion function of the shell.
208 Completion code suitable to be evaled is written to stdout if no argument
214 local a b ere tab=' '
216 _gsu_get_command_regex
219 if test -z "$1"; then
223 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
224 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
225 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
226 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
228 } | grep -v -- '--' \
229 | sed -En "/$ere/"'!d
230 # remove everything but the command name
231 s/^com_(.*)\(\).*/\1/
233 # append tab after short commands (less than 8 chars)
234 s/^(.{1,7})$/\1'"$tab"'/g
236 # remove next line (should contain only ## anyway)
240 # append next line, removing leading ##
244 # replace newline by tab
247 # and print the sucker
250 echo "# Try $_gsu_self help <command> for info on <command>."
254 if test "$1" = "help"; then
259 if test "$1" = "man"; then
264 if test "$1" = "prefs"; then
265 echo "$gsu_prefs_txt"
269 if test "$1" = "complete"; then
270 echo "$gsu_complete_txt"
275 _gsu_get_command_regex "$1"
277 if ! grep -Eq "$ere" $0; then
278 _gsu_print_available_commands
280 ret=-$E_GSU_BAD_COMMAND
284 # only consider lines in the comment of the function
290 # if it did start with ##, jump to label p and print it
293 # otherwise, move on to next line
305 _gsu_available_commands
309 # Wrapper for bash's getopts.
311 # Aborts on programming errors such as missing or invalid option string. On
312 # success $result contains shell code that can be eval'ed. For each defined
313 # option x, the local variable o_x will be created when calling eval "$result".
314 # o_x contains true/false for options without an argument or the emtpy string/the
315 # given argument, depending on whether this option was contained in the "$@"
319 # gsu_getopts abc:x:y
321 # [[ $ret -lt 0 ]] && return
323 # [[ "$o_a" = "true ]] && echo "The -a flag was given"
324 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
327 local i c tab=' ' cr='
330 gsu_check_arg_count $# 1 1
331 if [[ $ret -lt 0 ]]; then
337 result="invalid optstring $1"
338 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
343 for ((i=0; i < ${#1}; i++)); do
349 result="invalid character $c in optstring"
355 for ((i=0; i < ${#1}; i++)); do
357 c2=${1:$(($i + 1)):1}
359 if [[ "$c2" = ":" ]]; then
367 while getopts $1 opt \"\$@\"; do
370 for ((i=0; i < ${#1}; i++)); do
372 c2=${1:$(($i + 1)):1}
373 result+="$tab$tab$c1) o_$c1="
374 if [[ "$c2" = ":" ]]; then
375 result+="\"\$OPTARG\""
385 result=\"invalid option given\"
390 shift \$((\$OPTIND - 1))
397 local cmd n cword="$1"
402 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
405 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
406 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
410 [[ -z "$cword" ]] && return
411 if (($cword <= 1)); then
412 _gsu_available_commands
420 ret=$GSU_SUCCESS # It's not an error if no completer was defined
421 [[ "$(type -t complete_$cmd)" != "function" ]] && return
422 complete_$cmd "$cword" "${words[@]}"
423 # ignore errors, they would only clutter the completion output
427 gsu_cword_is_option_parameter()
429 local opts="$1" cword="$2" prev i n
433 (($cword == 0)) && return
434 ((${#opts} < 2)) && return
438 prev="${words[$(($cword - 1))]}"
439 [[ ! "$prev" == -* ]] && return
442 for ((i=0; i < $n; i++)); do
444 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
446 [[ "$prev" != "-$opt" ]] && continue
457 _gsu_available_commands
459 if test $# -eq 0; then
461 _gsu_print_available_commands
466 # check internal commands
467 if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
469 if [[ "$ret" -lt 0 ]]; then
477 for i in $gsu_cmds; do
478 if test "$arg" = "$i"; then
480 if [[ "$ret" -lt 0 ]]; then
488 ret=-$E_GSU_BAD_COMMAND
491 _gsu_print_available_commands
495 # Check number of arguments.
497 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
499 # Check that <num_given> is between <num1> and <num2> inclusively.
500 # If only <num1> ist given, num2 is assumed to be infinity.
503 # 0 0 no argument allowed
504 # 1 1 exactly one argument required
505 # 0 2 at most two arguments admissible
506 # 2 at least two arguments reqired
508 gsu_check_arg_count()
510 ret=-$E_GSU_BAD_ARG_COUNT
511 if [[ $# -eq 2 ]]; then # only num1 is given
512 result="at least $2 args required, $1 given"
513 [[ $1 -lt $2 ]] && return
517 # num1 and num2 given
518 result="need at least $2 args, $1 given"
519 [[ $1 -lt $2 ]] && return
520 result="need at most $3 args, $1 given"
521 [[ $1 -gt $3 ]] && return