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 # Wrapper for the bash getopts builtin.
84 # Aborts on programming errors such as missing or invalid option string. On
85 # success $result contains shell code that can be eval'ed. For each defined
86 # option x, the local variable o_x will be created when calling eval "$result".
87 # o_x contains true/false for options without argument and either the empty
88 # string or the given argument for options that take an argument.
93 # (($ret < 0)) && return
95 # [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
96 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
99 local i c tab=' ' cr='
102 gsu_check_arg_count $# 1 1
103 if (($ret < 0)); then
109 result="invalid optstring $1"
110 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
115 for ((i=0; i < ${#1}; i++)); do
121 result="invalid character $c in optstring"
126 result="local _gsu_getopts_opt"
127 for ((i=0; i < ${#1}; i++)); do
129 c2=${1:$(($i + 1)):1}
131 if [[ "$c2" = ":" ]]; then
139 while getopts $1 _gsu_getopts_opt \"\$@\"; do
140 case \"\$_gsu_getopts_opt\" in
142 for ((i=0; i < ${#1}; i++)); do
144 c2=${1:$(($i + 1)):1}
145 result+="$tab$tab$c1) o_$c1="
146 if [[ "$c2" = ":" ]]; then
147 result+="\"\$OPTARG\""
157 result=\"invalid option given\"
162 shift \$((\$OPTIND - 1))
167 _gsu_print_available_commands()
172 _gsu_available_commands
174 printf 'Available commands:\n'
178 if (($count % 4)); then
180 ((${#cmd} < 8)) && printf '\t'
188 # Print all options of the given optstring to stdout if the word in the current
189 # command line begins with a hyphen character.
190 gsu_complete_options()
192 local opts="$1" cword="$2" cur opt
197 cur="${words[$cword]}"
199 [[ ! "$cur" == -* ]] && return
202 for ((i=0; i < ${#opts}; i++)); do
204 [[ "$opt" == ":" ]] && continue
210 com_prefs_options='e'
213 Print the current preferences.
217 If -e is given, the config file is opened with the default editor.
218 Without options, the command prints out a list of all config variables,
219 together with their current value and the default value.
224 local i conf="${gsu_config_file:=${HOME:-}/.$gsu_name.rc}"
226 gsu_getopts "$com_prefs_options"
228 (($ret < 0)) && return
229 gsu_check_arg_count $# 0 0
230 (($ret < 0)) && return
232 if [[ "$o_e" == "true" ]]; then
236 (($? != 0)) && return
238 result="${EDITOR:-vi}"
240 (($? != 0)) && return
245 for ((i=0; i < ${#gsu_options[@]}; i++)); do
246 local name= option_type= default_value= required=
247 local description= help_text=
248 eval "${gsu_options[$i]}"
249 eval val='"${'${gsu_config_var_prefix}_$name:-'}"'
258 printf "%s: %s" "$option_type" "$description"
259 if [[ "$required" != "yes" && "$required" != "true" ]]; then
260 printf " [%s]" "$default_value"
263 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
264 printf "%s=%s" "$name" "$val"
265 [[ "$val" == "$default_value" ]] && printf " # default"
273 stty 0<&3 &> /dev/null
278 gsu_complete_options "$com_prefs_options" "$@"
286 If stdout associated with a terminal device, output is piped to
287 $PAGER. If $PAGER is unset, less(1) is assumed.
292 local equal_signs="=================================================="
293 local minus_signs="--------------------------------------------------"
294 local com num pager='cat'
296 _gsu_isatty && pager="${PAGER:-less}"
297 [[ "$pager" == 'less' ]] && export LESS=${LESS-RI}
299 echo "$gsu_name (_${gsu_banner_txt}_) manual"
300 echo "${equal_signs:0:${#gsu_name} + ${#gsu_banner_txt} + 16}"
303 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
306 echo "$gsu_name usage"
307 echo "${minus_signs:0:${#gsu_name} + 6}"
310 echo "Each command has its own set of options as described below."
314 echo "Available commands:"
316 _gsu_available_commands
317 for com in $result; do
319 (($num < 4)) && num=4
320 echo "${minus_signs:0:$num}"
322 echo "${minus_signs:0:$num}"
333 Usage: help [command]
335 Without arguments, print the list of available commands. Otherwise,
336 print the help text for the given command."
339 Command line completion.
341 Usage: complete [<cword> <word>...]
343 When executed without argument the command writes bash code to
344 stdout. This code is suitable to be evaled from .bashrc to enable
347 If at least one argument is given, all possible completions are
348 written to stdout. This can be used from the completion function of
356 _gsu_get_command_regex
360 gsu_short_msg "### $gsu_name -- $gsu_banner_txt ###"
363 printf "com_help()\n%s" "$_gsu_help_txt" | head -n 4; echo "--"
364 printf "com_man()\n%s" "$_gsu_man_txt" | head -n 4; echo "--"
365 printf "com_prefs()\n%s" "$_gsu_prefs_txt" | head -n 4; echo "--"
366 printf "com_complete()\n%s" "$_gsu_complete_txt" | head -n 4; echo "--"
367 grep -EA 2 "$ere" "$0"
368 } | grep -v -- '--' \
369 | sed -En "/$ere/"'!d
370 # remove everything but the command name
371 s/^com_(.*)\(\).*/\1/
373 # append tab after short commands (less than 8 chars)
374 s/^(.{1,7})$/\1'"$tab"'/g
376 # remove next line (should contain only ## anyway)
380 # append next line, removing leading ##
384 # replace newline by tab
387 # and print the sucker
390 echo "# Try $gsu_name help <command> for info on <command>."
394 if test "$1" = "help"; then
395 echo "$_gsu_help_txt"
399 if test "$1" = "man"; then
404 if test "$1" = "prefs"; then
405 echo "$_gsu_prefs_txt"
409 if test "$1" = "complete"; then
410 echo "$_gsu_complete_txt"
415 _gsu_get_command_regex "$1"
417 if ! grep -Eq "$ere" $0; then
418 _gsu_print_available_commands
420 ret=-$E_GSU_BAD_COMMAND
424 # only consider lines in the comment of the function
430 # if it did start with ##, jump to label p and print it
433 # otherwise, move on to next line
445 _gsu_available_commands
456 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
459 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
460 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
467 gsu_is_a_number "$cword"
468 (($ret < 0)) && return
469 if (($cword <= 1)); then
470 _gsu_available_commands
478 ret=$GSU_SUCCESS # It's not an error if no completer was defined
479 [[ "$(type -t complete_$cmd)" != "function" ]] && return
480 complete_$cmd "$cword" "${words[@]}"
481 # ignore errors, they would only clutter the completion output
485 # Find out if the current word is a parameter for an option.
487 # $1: usual getopts option string.
488 # $2: The current word number.
489 # $3..: All words of the current command line.
491 # return: If yes, $result contains the letter of the option for which the
492 # current word is a parameter. Otherwise, $result is empty.
494 gsu_cword_is_option_parameter()
496 local opts="$1" cword="$2" prev i n
500 (($cword == 0)) && return
501 ((${#opts} < 2)) && return
505 prev="${words[$(($cword - 1))]}"
506 [[ ! "$prev" == -* ]] && return
509 for ((i=0; i <= $n; i++)); do
511 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
513 [[ "$prev" != "-$opt" ]] && continue
520 # Get the word number on which the cursor is, not counting options.
522 # This is useful for completing commands whose possible completions depend
523 # on the word number, for example mount.
525 # $1: Getopt option string.
526 # $2: The current word number.
527 # $3..: All words of the current command line.
529 # return: If the current word is an option, or a parameter to an option,
530 # this function sets $result to -1. Otherwise, the number of the non-option
531 # is returned in $result.
533 gsu_get_unnamed_arg_num()
535 local opts="$1" cword="$2" prev cur
541 cur="${words[$cword]}"
542 prev="${words[$(($cword - 1))]}"
544 [[ "$cur" == -* ]] && return
545 [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return
547 for ((i=1; i <= $cword; i++)); do
548 prev="${words[$(($i - 1))]}"
550 [[ "$cur" == -* ]] && continue
551 if [[ "$prev" == -* ]]; then
553 [[ "$opts" != *$opt:* ]] && let n++
561 # Entry point for all gsu-based scripts.
563 # The startup part of the application script should source this file to load
564 # the functions defined here, and then call gsu(). Functions starting with com_
565 # are automatically recognized as subcommands.
573 # gsu_dir=${gsu_dir:-/system/location/where/gsu/is/installed}
574 # . $gsu_dir/subcommand || exit 1
582 _gsu_print_available_commands
587 if [[ "$(type -t com_$arg)" == 'function' ]]; then
589 if (("$ret" < 0)); then
595 ret=-$E_GSU_BAD_COMMAND
598 _gsu_print_available_commands