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 _gsu_available_commands
60 printf 'Available commands:\n'
64 if (($count % 4)); then
66 ((${#cmd} < 8)) && printf '\t'
74 # Print all options of the given optstring to stdout if the word in the current
75 # command line begins with a hyphen character.
76 gsu_complete_options()
78 local opts="$1" cword="$2" cur opt
83 cur="${words[$cword]}"
85 [[ ! "$cur" == -* ]] && return
88 for ((i=0; i < ${#opts}; i++)); do
90 [[ "$opt" == ":" ]] && continue
98 export gsu_prefs_txt="
99 Print the current preferences.
103 If -e is given, the config file is opened with the default editor.
104 Without options, the command prints out a list of all config variables,
105 together with their current value and the default value.
110 local i conf="${gsu_config_file:=${HOME:-}/.$gsu_name.rc}"
112 gsu_getopts "$com_prefs_options"
114 (($ret < 0)) && return
115 gsu_check_arg_count $# 0 0
116 (($ret < 0)) && return
118 if [[ "$o_e" == "true" ]]; then
122 (($? != 0)) && return
124 result="${EDITOR:-vi}"
126 (($? != 0)) && return
131 for ((i=0; i < ${#gsu_options[@]}; i++)); do
132 local name= option_type= default_value= required=
133 local description= help_text=
134 eval "${gsu_options[$i]}"
135 eval val='"${'${gsu_config_var_prefix}_$name:-'}"'
144 printf " $option_type: $description"
145 if [[ "$required" != "yes" && "$required" != "true" ]]; then
146 printf " [$default_value]"
149 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
151 [[ "$val" == "$default_value" ]] && printf " # default"
158 gsu_complete_options "$com_prefs_options" "$@"
169 local equal_signs="=================================================="
170 local minus_signs="--------------------------------------------------"
173 echo "$gsu_name (_${gsu_banner_txt}_) manual"
174 echo "${equal_signs:0:${#gsu_name} + ${#gsu_banner_txt} + 16}"
177 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
180 echo "$gsu_name usage"
181 echo "${minus_signs:0:${#gsu_name} + 6}"
184 echo "Each command has its own set of options as described below."
188 echo "Available commands:"
190 _gsu_available_commands
191 for com in $result; do
193 (($num < 4)) && num=4
194 echo "${minus_signs:0:$num}"
196 echo "${minus_signs:0:$num}"
203 export gsu_help_txt="
206 Usage: help [command]
208 Without arguments, print the list of available commands. Otherwise,
209 print the help text for the given command."
211 export gsu_complete_txt="
212 Command line completion.
214 Usage: complete [<cword> <word>...]
216 When executed without argument the command writes bash code to
217 stdout. This code is suitable to be evaled from .bashrc to enable
220 If at least one argument is given, all possible completions are
221 written to stdout. This can be used from the completion function of
227 local a b ere tab=' '
229 _gsu_get_command_regex
233 gsu_short_msg "### $gsu_name -- $gsu_banner_txt ###"
236 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
237 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
238 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
239 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
241 } | grep -v -- '--' \
242 | sed -En "/$ere/"'!d
243 # remove everything but the command name
244 s/^com_(.*)\(\).*/\1/
246 # append tab after short commands (less than 8 chars)
247 s/^(.{1,7})$/\1'"$tab"'/g
249 # remove next line (should contain only ## anyway)
253 # append next line, removing leading ##
257 # replace newline by tab
260 # and print the sucker
263 echo "# Try $gsu_name help <command> for info on <command>."
267 if test "$1" = "help"; then
272 if test "$1" = "man"; then
277 if test "$1" = "prefs"; then
278 echo "$gsu_prefs_txt"
282 if test "$1" = "complete"; then
283 echo "$gsu_complete_txt"
288 _gsu_get_command_regex "$1"
290 if ! grep -Eq "$ere" $0; then
291 _gsu_print_available_commands
293 ret=-$E_GSU_BAD_COMMAND
297 # only consider lines in the comment of the function
303 # if it did start with ##, jump to label p and print it
306 # otherwise, move on to next line
318 _gsu_available_commands
322 # Wrapper for the bash getopts builtin.
324 # Aborts on programming errors such as missing or invalid option string. On
325 # success $result contains shell code that can be eval'ed. For each defined
326 # option x, the local variable o_x will be created when calling eval "$result".
327 # o_x contains true/false for options without argument and either the empty
328 # string or the given argument for options that take an argument.
331 # gsu_getopts abc:x:y
333 # (($ret < 0)) && return
335 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
336 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
339 local i c tab=' ' cr='
342 gsu_check_arg_count $# 1 1
343 if (($ret < 0)); then
349 result="invalid optstring $1"
350 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
355 for ((i=0; i < ${#1}; i++)); do
361 result="invalid character $c in optstring"
366 result="local _gsu_getopts_opt"
367 for ((i=0; i < ${#1}; i++)); do
369 c2=${1:$(($i + 1)):1}
371 if [[ "$c2" = ":" ]]; then
379 while getopts $1 _gsu_getopts_opt \"\$@\"; do
380 case \"\$_gsu_getopts_opt\" in
382 for ((i=0; i < ${#1}; i++)); do
384 c2=${1:$(($i + 1)):1}
385 result+="$tab$tab$c1) o_$c1="
386 if [[ "$c2" = ":" ]]; then
387 result+="\"\$OPTARG\""
397 result=\"invalid option given\"
402 shift \$((\$OPTIND - 1))
414 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
417 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
418 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
425 gsu_is_a_number "$cword"
426 (($ret < 0)) && return
427 if (($cword <= 1)); then
428 _gsu_available_commands
436 ret=$GSU_SUCCESS # It's not an error if no completer was defined
437 [[ "$(type -t complete_$cmd)" != "function" ]] && return
438 complete_$cmd "$cword" "${words[@]}"
439 # ignore errors, they would only clutter the completion output
443 # Find out if the current word is a parameter for an option.
445 # $1: usual getopts option string.
446 # $2: The current word number.
447 # $3..: All words of the current command line.
449 # return: If yes, $result contains the letter of the option for which the
450 # current word is a parameter. Otherwise, $result is empty.
452 gsu_cword_is_option_parameter()
454 local opts="$1" cword="$2" prev i n
458 (($cword == 0)) && return
459 ((${#opts} < 2)) && return
463 prev="${words[$(($cword - 1))]}"
464 [[ ! "$prev" == -* ]] && return
467 for ((i=0; i <= $n; i++)); do
469 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
471 [[ "$prev" != "-$opt" ]] && continue
478 # Get the word number on which the cursor is, not counting options.
480 # This is useful for completing commands whose possible completions depend
481 # on the word number, for example mount.
483 # $1: Getopt option string.
484 # $2: The current word number.
485 # $3..: All words of the current command line.
487 # return: If the current word is an option, or a parameter to an option,
488 # this function sets $result to -1. Otherwise, the number of the non-option
489 # is returned in $result.
491 gsu_get_unnamed_arg_num()
493 local opts="$1" cword="$2" prev cur
499 cur="${words[$cword]}"
500 prev="${words[$(($cword - 1))]}"
502 [[ "$cur" == -* ]] && return
503 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
505 for ((i=1; i <= $cword; i++)); do
506 prev="${words[$(($i - 1))]}"
508 [[ "$cur" == -* ]] && continue
509 if [[ "$prev" == -* ]]; then
511 [[ "$opts" != *$opt:* ]] && let n++
519 # Entry point for all gsu-based scripts.
521 # The startup part of the application script should source this file to load
522 # the functions defined here, and then call gsu(). Functions starting with com_
523 # are automatically recognized as subcommands.
531 # gsu_dir=${gsu_dir:-/system/location/where/gsu/is/installed}
532 # . $gsu_dir/subcommand || exit 1
540 _gsu_print_available_commands
545 if [[ "$(type -t com_$arg)" == 'function' ]]; then
547 if (("$ret" < 0)); then
553 ret=-$E_GSU_BAD_COMMAND
556 _gsu_print_available_commands
560 # Check number of arguments.
562 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
564 # Check that <num_given> is between <num1> and <num2> inclusively.
565 # If only <num1> ist given, num2 is assumed to be infinity.
568 # 0 0 no argument allowed
569 # 1 1 exactly one argument required
570 # 0 2 at most two arguments admissible
571 # 2 at least two arguments required
572 gsu_check_arg_count()
574 ret=-$E_GSU_BAD_ARG_COUNT
575 if (($# == 2)); then # only num1 is given
576 result="at least $2 args required, $1 given"
577 (($1 < $2)) && return
581 # num1 and num2 given
582 result="need at least $2 args, $1 given"
583 (($1 < $2)) && return
584 result="need at most $3 args, $1 given"
585 (($1 > $3)) && return