2 # Copyright (C) 2006 Andre Noll
3 # Licensed under the LGPL, version 3. See COPYING and COPYING.LESSER.
5 if [[ "$(type -t _gsu_setup)" != "function" ]]; then
6 gsu_dir=${gsu_dir:-${BASH_SOURCE[0]%/*}}
7 . $gsu_dir/common || exit 1
13 gsu_short_msg "# Usage: $gsu_name command [options]"
16 # Return an extended regular expression to match against $0.
18 # When called without argument, the expression matches all lines which define a
21 # If an argument is given, the returned expression matches only the subcommand
22 # passed as $1. This is useful to tell if a string is a valid subcommand.
24 # Regardless of whether an argument is given, the returned expression contains
25 # exactly one parenthesized subexpression for matching the command name.
26 _gsu_get_command_regex()
28 local cmd="${1:-[-a-zA-Z_0-9]{1,\}}"
29 result="^com_($cmd)\(\)"
32 _gsu_available_commands()
36 _gsu_get_command_regex
39 printf "help\nman\nprefs\ncomplete\n"
41 # if line matches, isolate command name
44 # if there is a match, (print it and) start next cycle
50 } | sort | tr '\n' ' ')"
53 _gsu_print_available_commands()
58 printf 'Available commands:\n'
59 for cmd in $gsu_cmds; do
62 if (($count % 4)); then
64 ((${#cmd} < 8)) && printf '\t'
72 # Print all options of the given optstring to stdout if the word in the current
73 # command line begins with a hyphen character.
74 gsu_complete_options()
76 local opts="$1" cword="$2" cur opt
81 cur="${words[$cword]}"
83 [[ ! "$cur" == -* ]] && return
86 for ((i=0; i < ${#opts}; i++)); do
88 [[ "$opt" == ":" ]] && continue
94 export gsu_prefs_txt="
95 Print the current preferences.
99 If -e is given, the config file is opened with the default editor.
100 Without options, the command prints out a list of all config variables,
101 together with their current value and the default value.
105 local i conf="${gsu_config_file:=${HOME:-}/.$gsu_name.rc}"
109 (($ret < 0)) && return
110 gsu_check_arg_count $# 0 0
111 (($ret < 0)) && return
113 if [[ "$o_e" == "true" ]]; then
117 (($? != 0)) && return
119 result="${EDITOR:-vi}"
121 (($? != 0)) && return
126 for ((i=0; i < ${#gsu_options[@]}; i++)); do
127 local name= option_type= default_value= required=
128 local description= help_text=
129 eval "${gsu_options[$i]}"
130 eval val='"${'${gsu_config_var_prefix}_$name:-'}"'
139 printf " $option_type: $description"
140 if [[ "$required" != "yes" && "$required" != "true" ]]; then
141 printf " [$default_value]"
144 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
146 [[ "$val" == "$default_value" ]] && printf " # default"
153 gsu_complete_options "e" "$@"
163 local equal_signs="=================================================="
164 local minus_signs="--------------------------------------------------"
167 echo "$gsu_name (_${gsu_banner_txt}_) manual"
168 echo "${equal_signs:0:${#gsu_name} + ${#gsu_banner_txt} + 16}"
171 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
174 echo "$gsu_name usage"
175 echo "${minus_signs:0:${#gsu_name} + 6}"
178 echo "Each command has its own set of options as described below."
182 echo "Available commands:"
184 _gsu_available_commands
185 for com in $result; do
187 (($num < 4)) && num=4
188 echo "${minus_signs:0:$num}"
190 echo "${minus_signs:0:$num}"
197 export gsu_help_txt="
200 Usage: help [command]
202 Without arguments, print the list of available commands. Otherwise,
203 print the help text for the given command."
205 export gsu_complete_txt="
206 Command line completion.
208 Usage: complete [<cword> <word>...]
210 When executed without argument the command writes bash code to
211 stdout. This code is suitable to be evaled from .bashrc to enable
214 If at least one argument is given, all possible completions are
215 written to stdout. This can be used from the completion function of
221 local a b ere tab=' '
223 _gsu_get_command_regex
227 gsu_short_msg "### $gsu_name -- $gsu_banner_txt ###"
230 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
231 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
232 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
233 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
235 } | grep -v -- '--' \
236 | sed -En "/$ere/"'!d
237 # remove everything but the command name
238 s/^com_(.*)\(\).*/\1/
240 # append tab after short commands (less than 8 chars)
241 s/^(.{1,7})$/\1'"$tab"'/g
243 # remove next line (should contain only ## anyway)
247 # append next line, removing leading ##
251 # replace newline by tab
254 # and print the sucker
257 echo "# Try $gsu_name help <command> for info on <command>."
261 if test "$1" = "help"; then
266 if test "$1" = "man"; then
271 if test "$1" = "prefs"; then
272 echo "$gsu_prefs_txt"
276 if test "$1" = "complete"; then
277 echo "$gsu_complete_txt"
282 _gsu_get_command_regex "$1"
284 if ! grep -Eq "$ere" $0; then
285 _gsu_print_available_commands
287 ret=-$E_GSU_BAD_COMMAND
291 # only consider lines in the comment of the function
297 # if it did start with ##, jump to label p and print it
300 # otherwise, move on to next line
312 _gsu_available_commands
316 # Wrapper for the bash getopts builtin.
318 # Aborts on programming errors such as missing or invalid option string. On
319 # success $result contains shell code that can be eval'ed. For each defined
320 # option x, the local variable o_x will be created when calling eval "$result".
321 # o_x contains true/false for options without argument and either the empty
322 # string or the given argument for options that take an argument.
325 # gsu_getopts abc:x:y
327 # (($ret < 0)) && return
329 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
330 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
333 local i c tab=' ' cr='
336 gsu_check_arg_count $# 1 1
337 if (($ret < 0)); then
343 result="invalid optstring $1"
344 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
349 for ((i=0; i < ${#1}; i++)); do
355 result="invalid character $c in optstring"
360 result="local _gsu_getopts_opt"
361 for ((i=0; i < ${#1}; i++)); do
363 c2=${1:$(($i + 1)):1}
365 if [[ "$c2" = ":" ]]; then
373 while getopts $1 _gsu_getopts_opt \"\$@\"; do
374 case \"\$_gsu_getopts_opt\" in
376 for ((i=0; i < ${#1}; i++)); do
378 c2=${1:$(($i + 1)):1}
379 result+="$tab$tab$c1) o_$c1="
380 if [[ "$c2" = ":" ]]; then
381 result+="\"\$OPTARG\""
391 result=\"invalid option given\"
396 shift \$((\$OPTIND - 1))
408 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
411 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
412 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
419 gsu_is_a_number "$cword"
420 (($ret < 0)) && return
421 if (($cword <= 1)); then
422 _gsu_available_commands
430 ret=$GSU_SUCCESS # It's not an error if no completer was defined
431 [[ "$(type -t complete_$cmd)" != "function" ]] && return
432 complete_$cmd "$cword" "${words[@]}"
433 # ignore errors, they would only clutter the completion output
437 # Find out if the current word is a parameter for an option.
439 # $1: usual getopts option string.
440 # $2: The current word number.
441 # $3..: All words of the current command line.
443 # return: If yes, $result contains the letter of the option for which the
444 # current word is a parameter. Otherwise, $result is empty.
446 gsu_cword_is_option_parameter()
448 local opts="$1" cword="$2" prev i n
452 (($cword == 0)) && return
453 ((${#opts} < 2)) && return
457 prev="${words[$(($cword - 1))]}"
458 [[ ! "$prev" == -* ]] && return
461 for ((i=0; i <= $n; i++)); do
463 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
465 [[ "$prev" != "-$opt" ]] && continue
472 # Get the word number on which the cursor is, not counting options.
474 # This is useful for completing commands whose possible completions depend
475 # on the word number, for example mount.
477 # $1: Getopt option string.
478 # $2: The current word number.
479 # $3..: All words of the current command line.
481 # return: If the current word is an option, or a parameter to an option,
482 # this function sets $result to -1. Otherwise, the number of the non-option
483 # is returned in $result.
485 gsu_get_unnamed_arg_num()
487 local opts="$1" cword="$2" prev cur
493 cur="${words[$cword]}"
494 prev="${words[$(($cword - 1))]}"
496 [[ "$cur" == -* ]] && return
497 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
499 for ((i=1; i <= $cword; i++)); do
500 prev="${words[$(($i - 1))]}"
502 [[ "$cur" == -* ]] && continue
503 if [[ "$prev" == -* ]]; then
505 [[ "$opts" != *$opt:* ]] && let n++
513 # Entry point for all gsu-based scripts.
515 # The startup part of the application script should source this file to load
516 # the functions defined here, and then call gsu(). Functions starting with com_
517 # are automatically recognized as subcommands.
525 # gsu_dir=${gsu_dir:-/system/location/where/gsu/is/installed}
526 # . $gsu_dir/subcommand || exit 1
531 _gsu_available_commands
535 _gsu_print_available_commands
540 # check internal commands
541 if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
543 if (("$ret" < 0)); then
551 for i in $gsu_cmds; do
552 if test "$arg" = "$i"; then
555 if (("$ret" < 0)); then
563 ret=-$E_GSU_BAD_COMMAND
566 _gsu_print_available_commands
570 # Check number of arguments.
572 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
574 # Check that <num_given> is between <num1> and <num2> inclusively.
575 # If only <num1> ist given, num2 is assumed to be infinity.
578 # 0 0 no argument allowed
579 # 1 1 exactly one argument required
580 # 0 2 at most two arguments admissible
581 # 2 at least two arguments required
582 gsu_check_arg_count()
584 ret=-$E_GSU_BAD_ARG_COUNT
585 if (($# == 2)); then # only num1 is given
586 result="at least $2 args required, $1 given"
587 (($1 < $2)) && return
591 # num1 and num2 given
592 result="need at least $2 args, $1 given"
593 (($1 < $2)) && return
594 result="need at most $3 args, $1 given"
595 (($1 > $3)) && return