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 # Check number of arguments.
55 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
57 # Check that <num_given> is between <num1> and <num2> inclusively.
58 # If only <num1> ist given, num2 is assumed to be infinity.
61 # 0 0 no argument allowed
62 # 1 1 exactly one argument required
63 # 0 2 at most two arguments admissible
64 # 2 at least two arguments required
67 ret=-$E_GSU_BAD_ARG_COUNT
68 if (($# == 2)); then # only num1 is given
69 result="at least $2 args required, $1 given"
75 result="need at least $2 args, $1 given"
77 result="need at most $3 args, $1 given"
82 _gsu_print_available_commands()
87 _gsu_available_commands
89 printf 'Available commands:\n'
93 if (($count % 4)); then
95 ((${#cmd} < 8)) && printf '\t'
103 # Print all options of the given optstring to stdout if the word in the current
104 # command line begins with a hyphen character.
105 gsu_complete_options()
107 local opts="$1" cword="$2" cur opt
112 cur="${words[$cword]}"
114 [[ ! "$cur" == -* ]] && return
117 for ((i=0; i < ${#opts}; i++)); do
119 [[ "$opt" == ":" ]] && continue
125 com_prefs_options='e'
127 export gsu_prefs_txt="
128 Print the current preferences.
132 If -e is given, the config file is opened with the default editor.
133 Without options, the command prints out a list of all config variables,
134 together with their current value and the default value.
139 local i conf="${gsu_config_file:=${HOME:-}/.$gsu_name.rc}"
141 gsu_getopts "$com_prefs_options"
143 (($ret < 0)) && return
144 gsu_check_arg_count $# 0 0
145 (($ret < 0)) && return
147 if [[ "$o_e" == "true" ]]; then
151 (($? != 0)) && return
153 result="${EDITOR:-vi}"
155 (($? != 0)) && return
160 for ((i=0; i < ${#gsu_options[@]}; i++)); do
161 local name= option_type= default_value= required=
162 local description= help_text=
163 eval "${gsu_options[$i]}"
164 eval val='"${'${gsu_config_var_prefix}_$name:-'}"'
173 printf " $option_type: $description"
174 if [[ "$required" != "yes" && "$required" != "true" ]]; then
175 printf " [$default_value]"
178 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
180 [[ "$val" == "$default_value" ]] && printf " # default"
187 gsu_complete_options "$com_prefs_options" "$@"
198 local equal_signs="=================================================="
199 local minus_signs="--------------------------------------------------"
202 echo "$gsu_name (_${gsu_banner_txt}_) manual"
203 echo "${equal_signs:0:${#gsu_name} + ${#gsu_banner_txt} + 16}"
206 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
209 echo "$gsu_name usage"
210 echo "${minus_signs:0:${#gsu_name} + 6}"
213 echo "Each command has its own set of options as described below."
217 echo "Available commands:"
219 _gsu_available_commands
220 for com in $result; do
222 (($num < 4)) && num=4
223 echo "${minus_signs:0:$num}"
225 echo "${minus_signs:0:$num}"
232 export gsu_help_txt="
235 Usage: help [command]
237 Without arguments, print the list of available commands. Otherwise,
238 print the help text for the given command."
240 export gsu_complete_txt="
241 Command line completion.
243 Usage: complete [<cword> <word>...]
245 When executed without argument the command writes bash code to
246 stdout. This code is suitable to be evaled from .bashrc to enable
249 If at least one argument is given, all possible completions are
250 written to stdout. This can be used from the completion function of
256 local a b ere tab=' '
258 _gsu_get_command_regex
262 gsu_short_msg "### $gsu_name -- $gsu_banner_txt ###"
265 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
266 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
267 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
268 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
270 } | grep -v -- '--' \
271 | sed -En "/$ere/"'!d
272 # remove everything but the command name
273 s/^com_(.*)\(\).*/\1/
275 # append tab after short commands (less than 8 chars)
276 s/^(.{1,7})$/\1'"$tab"'/g
278 # remove next line (should contain only ## anyway)
282 # append next line, removing leading ##
286 # replace newline by tab
289 # and print the sucker
292 echo "# Try $gsu_name help <command> for info on <command>."
296 if test "$1" = "help"; then
301 if test "$1" = "man"; then
306 if test "$1" = "prefs"; then
307 echo "$gsu_prefs_txt"
311 if test "$1" = "complete"; then
312 echo "$gsu_complete_txt"
317 _gsu_get_command_regex "$1"
319 if ! grep -Eq "$ere" $0; then
320 _gsu_print_available_commands
322 ret=-$E_GSU_BAD_COMMAND
326 # only consider lines in the comment of the function
332 # if it did start with ##, jump to label p and print it
335 # otherwise, move on to next line
347 _gsu_available_commands
351 # Wrapper for the bash getopts builtin.
353 # Aborts on programming errors such as missing or invalid option string. On
354 # success $result contains shell code that can be eval'ed. For each defined
355 # option x, the local variable o_x will be created when calling eval "$result".
356 # o_x contains true/false for options without argument and either the empty
357 # string or the given argument for options that take an argument.
360 # gsu_getopts abc:x:y
362 # (($ret < 0)) && return
364 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
365 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
368 local i c tab=' ' cr='
371 gsu_check_arg_count $# 1 1
372 if (($ret < 0)); then
378 result="invalid optstring $1"
379 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
384 for ((i=0; i < ${#1}; i++)); do
390 result="invalid character $c in optstring"
395 result="local _gsu_getopts_opt"
396 for ((i=0; i < ${#1}; i++)); do
398 c2=${1:$(($i + 1)):1}
400 if [[ "$c2" = ":" ]]; then
408 while getopts $1 _gsu_getopts_opt \"\$@\"; do
409 case \"\$_gsu_getopts_opt\" in
411 for ((i=0; i < ${#1}; i++)); do
413 c2=${1:$(($i + 1)):1}
414 result+="$tab$tab$c1) o_$c1="
415 if [[ "$c2" = ":" ]]; then
416 result+="\"\$OPTARG\""
426 result=\"invalid option given\"
431 shift \$((\$OPTIND - 1))
443 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
446 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
447 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
454 gsu_is_a_number "$cword"
455 (($ret < 0)) && return
456 if (($cword <= 1)); then
457 _gsu_available_commands
465 ret=$GSU_SUCCESS # It's not an error if no completer was defined
466 [[ "$(type -t complete_$cmd)" != "function" ]] && return
467 complete_$cmd "$cword" "${words[@]}"
468 # ignore errors, they would only clutter the completion output
472 # Find out if the current word is a parameter for an option.
474 # $1: usual getopts option string.
475 # $2: The current word number.
476 # $3..: All words of the current command line.
478 # return: If yes, $result contains the letter of the option for which the
479 # current word is a parameter. Otherwise, $result is empty.
481 gsu_cword_is_option_parameter()
483 local opts="$1" cword="$2" prev i n
487 (($cword == 0)) && return
488 ((${#opts} < 2)) && return
492 prev="${words[$(($cword - 1))]}"
493 [[ ! "$prev" == -* ]] && return
496 for ((i=0; i <= $n; i++)); do
498 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
500 [[ "$prev" != "-$opt" ]] && continue
507 # Get the word number on which the cursor is, not counting options.
509 # This is useful for completing commands whose possible completions depend
510 # on the word number, for example mount.
512 # $1: Getopt option string.
513 # $2: The current word number.
514 # $3..: All words of the current command line.
516 # return: If the current word is an option, or a parameter to an option,
517 # this function sets $result to -1. Otherwise, the number of the non-option
518 # is returned in $result.
520 gsu_get_unnamed_arg_num()
522 local opts="$1" cword="$2" prev cur
528 cur="${words[$cword]}"
529 prev="${words[$(($cword - 1))]}"
531 [[ "$cur" == -* ]] && return
532 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
534 for ((i=1; i <= $cword; i++)); do
535 prev="${words[$(($i - 1))]}"
537 [[ "$cur" == -* ]] && continue
538 if [[ "$prev" == -* ]]; then
540 [[ "$opts" != *$opt:* ]] && let n++
548 # Entry point for all gsu-based scripts.
550 # The startup part of the application script should source this file to load
551 # the functions defined here, and then call gsu(). Functions starting with com_
552 # are automatically recognized as subcommands.
560 # gsu_dir=${gsu_dir:-/system/location/where/gsu/is/installed}
561 # . $gsu_dir/subcommand || exit 1
569 _gsu_print_available_commands
574 if [[ "$(type -t com_$arg)" == 'function' ]]; then
576 if (("$ret" < 0)); then
582 ret=-$E_GSU_BAD_COMMAND
585 _gsu_print_available_commands