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]+}"
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. Without
100 options, the command prints out a list of all cmt config variables, together
101 with their current value and the default value."
104 local i conf="${gsu_config_file:=${HOME:-}/.$gsu_name.rc}"
108 (($ret < 0)) && return
109 gsu_check_arg_count $# 0 0
110 (($ret < 0)) && return
112 if [[ "$o_e" == "true" ]]; then
116 (($? != 0)) && return
118 result="${EDITOR:-vi}"
120 (($? != 0)) && return
125 for ((i=0; i < ${#gsu_options[@]}; i++)); do
126 local name= option_type= default_value= required=
127 local description= help_text=
128 eval "${gsu_options[$i]}"
129 eval val='"${'${gsu_config_var_prefix}_$name:-'}"'
138 printf " $option_type: $description"
139 if [[ "$required" != "yes" && "$required" != "true" ]]; then
140 printf " [$default_value]"
143 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
145 [[ "$val" == "$default_value" ]] && printf " # default"
152 gsu_complete_options "e" "$@"
162 local equal_signs="=================================================="
163 local minus_signs="--------------------------------------------------"
166 echo "$gsu_name (_${gsu_banner_txt}_) manual"
167 echo "${equal_signs:0:${#gsu_name} + ${#gsu_banner_txt} + 16}"
170 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
173 echo "$gsu_name usage"
174 echo "${minus_signs:0:${#gsu_name} + 6}"
177 echo "Each command has its own set of options as described below."
181 echo "Available commands:"
183 _gsu_available_commands
184 for com in $result; do
186 (($num < 4)) && num=4
187 echo "${minus_signs:0:$num}"
189 echo "${minus_signs:0:$num}"
196 export gsu_help_txt="
199 Usage: help [command]
201 Without arguments, print the list of available commands. Otherwise,
202 print the help text for the given command."
204 export gsu_complete_txt="
205 Command line completion.
207 Usage: complete [<cword> <word>...]
209 When executed without argument the command writes bash code to
210 stdout. This code is suitable to be evaled from .bashrc to enable
213 If at least one argument is given, all possible completions are
214 written to stdout. This can be used from the completion function of
220 local a b ere tab=' '
222 _gsu_get_command_regex
226 gsu_short_msg "### $gsu_name -- $gsu_banner_txt ###"
229 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
230 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
231 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
232 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
234 } | grep -v -- '--' \
235 | sed -En "/$ere/"'!d
236 # remove everything but the command name
237 s/^com_(.*)\(\).*/\1/
239 # append tab after short commands (less than 8 chars)
240 s/^(.{1,7})$/\1'"$tab"'/g
242 # remove next line (should contain only ## anyway)
246 # append next line, removing leading ##
250 # replace newline by tab
253 # and print the sucker
256 echo "# Try $gsu_name help <command> for info on <command>."
260 if test "$1" = "help"; then
265 if test "$1" = "man"; then
270 if test "$1" = "prefs"; then
271 echo "$gsu_prefs_txt"
275 if test "$1" = "complete"; then
276 echo "$gsu_complete_txt"
281 _gsu_get_command_regex "$1"
283 if ! grep -Eq "$ere" $0; then
284 _gsu_print_available_commands
286 ret=-$E_GSU_BAD_COMMAND
290 # only consider lines in the comment of the function
296 # if it did start with ##, jump to label p and print it
299 # otherwise, move on to next line
311 _gsu_available_commands
315 # Wrapper for the bash getopts builtin.
317 # Aborts on programming errors such as missing or invalid option string. On
318 # success $result contains shell code that can be eval'ed. For each defined
319 # option x, the local variable o_x will be created when calling eval "$result".
320 # o_x contains true/false for options without argument and either the empty
321 # string or the given argument for options that take an argument.
324 # gsu_getopts abc:x:y
326 # (($ret < 0)) && return
328 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
329 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
332 local i c tab=' ' cr='
335 gsu_check_arg_count $# 1 1
336 if (($ret < 0)); then
342 result="invalid optstring $1"
343 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
348 for ((i=0; i < ${#1}; i++)); do
354 result="invalid character $c in optstring"
359 result="local _gsu_getopts_opt"
360 for ((i=0; i < ${#1}; i++)); do
362 c2=${1:$(($i + 1)):1}
364 if [[ "$c2" = ":" ]]; then
372 while getopts $1 _gsu_getopts_opt \"\$@\"; do
373 case \"\$_gsu_getopts_opt\" in
375 for ((i=0; i < ${#1}; i++)); do
377 c2=${1:$(($i + 1)):1}
378 result+="$tab$tab$c1) o_$c1="
379 if [[ "$c2" = ":" ]]; then
380 result+="\"\$OPTARG\""
390 result=\"invalid option given\"
395 shift \$((\$OPTIND - 1))
407 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
410 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
411 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
418 gsu_is_a_number "$cword"
419 (($ret < 0)) && return
420 if (($cword <= 1)); then
421 _gsu_available_commands
429 ret=$GSU_SUCCESS # It's not an error if no completer was defined
430 [[ "$(type -t complete_$cmd)" != "function" ]] && return
431 complete_$cmd "$cword" "${words[@]}"
432 # ignore errors, they would only clutter the completion output
436 # Find out if the current word is a parameter for an option.
438 # $1: usual getopts option string.
439 # $2: The current word number.
440 # $3..: All words of the current command line.
442 # return: If yes, $result contains the letter of the option for which the
443 # current word is a parameter. Otherwise, $result is empty.
445 gsu_cword_is_option_parameter()
447 local opts="$1" cword="$2" prev i n
451 (($cword == 0)) && return
452 ((${#opts} < 2)) && return
456 prev="${words[$(($cword - 1))]}"
457 [[ ! "$prev" == -* ]] && return
460 for ((i=0; i <= $n; i++)); do
462 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
464 [[ "$prev" != "-$opt" ]] && continue
471 # Get the word number on which the cursor is, not counting options.
473 # This is useful for completing commands whose possible completions depend
474 # on the word number, for example mount.
476 # $1: Getopt option string.
477 # $2: The current word number.
478 # $3..: All words of the current command line.
480 # return: If the current word is an option, or a parameter to an option,
481 # this function sets $result to -1. Otherwise, the number of the non-option
482 # is returned in $result.
484 gsu_get_unnamed_arg_num()
486 local opts="$1" cword="$2" prev cur
492 cur="${words[$cword]}"
493 prev="${words[$(($cword - 1))]}"
495 [[ "$cur" == -* ]] && return
496 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
498 for ((i=1; i <= $cword; i++)); do
499 prev="${words[$(($i - 1))]}"
501 [[ "$cur" == -* ]] && continue
502 if [[ "$prev" == -* ]]; then
504 [[ "$opts" != *$opt:* ]] && let n++
512 # Entry point for all gsu-based scripts.
514 # The startup part of the application script should source this file to load
515 # the functions defined here, and then call gsu(). Functions starting with com_
516 # are automatically recognized as subcommands.
524 # gsu_dir=${gsu_dir:-/system/location/where/gsu/is/installed}
525 # . $gsu_dir/subcommand || exit 1
530 _gsu_available_commands
534 _gsu_print_available_commands
539 # check internal commands
540 if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
542 if (("$ret" < 0)); then
550 for i in $gsu_cmds; do
551 if test "$arg" = "$i"; then
554 if (("$ret" < 0)); then
562 ret=-$E_GSU_BAD_COMMAND
565 _gsu_print_available_commands
569 # Check number of arguments.
571 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
573 # Check that <num_given> is between <num1> and <num2> inclusively.
574 # If only <num1> ist given, num2 is assumed to be infinity.
577 # 0 0 no argument allowed
578 # 1 1 exactly one argument required
579 # 0 2 at most two arguments admissible
580 # 2 at least two arguments required
581 gsu_check_arg_count()
583 ret=-$E_GSU_BAD_ARG_COUNT
584 if (($# == 2)); then # only num1 is given
585 result="at least $2 args required, $1 given"
586 (($1 < $2)) && return
590 # num1 and num2 given
591 result="need at least $2 args, $1 given"
592 (($1 < $2)) && return
593 result="need at most $3 args, $1 given"
594 (($1 > $3)) && return