2 # (C) 2006-2011 Andre Noll
4 if [[ $(type -t gsu_is_a_number) != "function" ]]; then
5 GSU_DIR=${GSU_DIR:=$HOME/.gsu}
6 . $GSU_DIR/common || exit 1
11 gsu_short_msg "# Usage: $_gsu_self command [options]"
14 # Each line matching this is recognized as a subcommand. The name
15 # of the subcommand is the first subexpression.
16 export gsu_command_regex='^com_\([-a-zA-Z_0-9]\+\)()'
18 _gsu_available_commands()
21 printf "help\nman\nprefs\ncomplete\n"
22 sed -ne "s/$gsu_command_regex/\1/g;T;p" $0
23 } | sort | tr '\n' ' ')"
26 _gsu_print_available_commands()
29 gsu_short_msg "Available commands:"
30 for i in $gsu_cmds; do
33 if test $(($count % 4)) -eq 0; then
37 if test ${#i} -lt 8; then
46 gsu_complete_options()
48 local opts="$1" cword="$2" cur
53 cur="${words[$cword]}"
55 [[ ! "$cur" == -* ]] && return
58 for ((i=0; i < ${#opts}; i++)); do
60 [[ "$opt" == ":" ]] && continue
66 export gsu_prefs_txt="
67 Print the current preferences.
71 If -e is given, the config file is opened with the default editor. Without
72 options, the command prints out a list of all cmt config variables, together
73 with their current value and the default value."
76 local i conf="${gsu_config_file:=$HOME/.$gsu_name.rc}"
78 if [[ "$1" = "-e" ]]; then
82 [[ $? -ne 0 ]] && return
84 result="${EDITOR:-vi}"
86 [[ $? -ne 0 ]] && return
91 for ((i=0; i < ${#gsu_options[@]}; i++)); do
92 local name= option_type= default_value= required=
93 local description= help_text=
94 eval "${gsu_options[$i]}"
95 eval val='"$'${gsu_config_var_prefix}_$name'"'
104 printf " $option_type: $description"
105 if [[ "$required" != "yes" && "$required" != "true" ]]; then
106 printf " [$default_value]"
109 [[ -n "$help_text" ]] && sed -e '/^[ ]*$/d; s/^[ ]*/# /g' <<< "$help_text"
111 [[ "$val" == "$default_value" ]] && printf " # default"
118 gsu_complete_options "e" "$@"
128 local equal_signs="=================================================="
129 local minus_signs="--------------------------------------------------"
132 echo "$_gsu_self (_${gsu_banner_txt}_) manual"
133 echo "${equal_signs:0:${#_gsu_self} + ${#gsu_banner_txt} + 16}"
136 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
139 echo "$_gsu_self usage"
140 echo "${minus_signs:0:${#_gsu_self} + 6}"
143 echo "Each command has its own set of options as described below."
147 echo "Available commands:"
149 _gsu_available_commands
150 for com in $result; do
152 if test $num -lt 4; then
155 echo "${minus_signs:0:$num}"
157 echo "${minus_signs:0:$num}"
166 local txt="### $_gsu_self --"
167 if test -z "$gsu_banner_txt"; then
168 txt="$txt set \$gsu_banner_txt to customize this message"
170 txt="$txt $gsu_banner_txt"
172 gsu_short_msg "$txt ###"
175 export gsu_help_txt="
178 Usage: help [command]
180 Without arguments, print the list of available commands. Otherwise,
181 print the help text for the given command."
183 export gsu_complete_txt="
184 Command line completion.
186 Usage: complete [<cword> <word>...]
188 In the first form, the command prints all possible completions to stdout.
189 This can be used from the completion function of the shell.
191 Completion code suitable to be evaled is written to stdout if no argument
198 if test -z "$1"; then
202 printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
203 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
204 printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
205 printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
206 grep -A 2 "$gsu_command_regex" $0
207 } | grep -v -- '--' \
208 | sed -e "/$gsu_command_regex/bs" \
209 -e 'H;$!d;x;s/\n//g;b' \
211 -e 'x;s/\n//g;${p;x;}' \
212 | sed -e "s/${gsu_command_regex}#*/\1\t/" \
216 if test ${#a} -lt 8; then
222 echo "# Try $_gsu_self help <command> for info on <command>."
226 if test "$1" = "help"; then
231 if test "$1" = "man"; then
236 if test "$1" = "prefs"; then
237 echo "$gsu_prefs_txt"
241 if test "$1" = "complete"; then
242 echo "$gsu_complete_txt"
247 if grep -q "^com_$1()" $0; then
248 sed -e "1,/^com_$1()$/d" -e '/^{/,$d' -e 's/^## *//' $0
251 _gsu_print_available_commands
253 ret=-$E_GSU_BAD_COMMAND
258 _gsu_available_commands
262 # Wrapper for bash's getopts.
264 # Aborts on programming errors such as missing or invalid option string. On
265 # success $result contains shell code that can be eval'ed. For each defined
266 # option x, the local variable o_x will be created when calling eval "$result".
267 # o_x contains true/false for options without an argument or the emtpy string/the
268 # given argument, depending on whether this option was contained in the "$@"
272 # gsu_getopts abc:x:y
274 # [[ $ret -lt 0 ]] && return
276 # [[ "$o_a" = "true ]] && echo "The -a flag was given"
277 # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
280 local i c tab=' ' cr='
283 gsu_check_arg_count $# 1 1
284 if [[ $ret -lt 0 ]]; then
290 result="invalid optstring $1"
291 if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
296 for ((i=0; i < ${#1}; i++)); do
302 result="invalid character $c in optstring"
308 for ((i=0; i < ${#1}; i++)); do
310 c2=${1:$(($i + 1)):1}
312 if [[ "$c2" = ":" ]]; then
320 while getopts $1 opt \"\$@\"; do
323 for ((i=0; i < ${#1}; i++)); do
325 c2=${1:$(($i + 1)):1}
326 result+="$tab$tab$c1) o_$c1="
327 if [[ "$c2" = ":" ]]; then
328 result+="\"\$OPTARG\""
338 result=\"invalid option given\"
343 shift \$((\$OPTIND - 1))
350 local cmd n cword="$1"
355 local cur="\${COMP_WORDS[\$COMP_CWORD]}";
358 candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
359 COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
363 [[ -z "$cword" ]] && return
364 if (($cword <= 1)); then
365 _gsu_available_commands
373 ret=$GSU_SUCCESS # It's not an error if no completer was defined
374 [[ "$(type -t complete_$cmd)" != "function" ]] && return
375 complete_$cmd "$cword" "${words[@]}"
376 # ignore errors, they would only clutter the completion output
380 gsu_cword_is_option_parameter()
382 local opts="$1" cword="$2" prev i n
386 (($cword == 0)) && return
387 ((${#opts} < 2)) && return
391 prev="${words[$(($cword - 1))]}"
392 [[ ! "$prev" == -* ]] && return
395 for ((i=0; i < $n; i++)); do
397 [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
399 [[ "$prev" != "-$opt" ]] && continue
410 _gsu_available_commands
412 if test $# -eq 0; then
414 _gsu_print_available_commands
419 # check internal commands
420 if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
422 if [[ "$ret" -lt 0 ]]; then
430 for i in $gsu_cmds; do
431 if test "$arg" = "$i"; then
433 if [[ "$ret" -lt 0 ]]; then
441 ret=-$E_GSU_BAD_COMMAND
444 _gsu_print_available_commands
448 # Check number of arguments.
450 # Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
452 # Check that <num_given> is between <num1> and <num2> inclusively.
453 # If only <num1> ist given, num2 is assumed to be infinity.
456 # 0 0 no argument allowed
457 # 1 1 exactly one argument required
458 # 0 2 at most two arguments admissible
459 # 2 at least two arguments reqired
461 gsu_check_arg_count()
463 ret=-$E_GSU_BAD_ARG_COUNT
464 if [[ $# -eq 2 ]]; then # only num1 is given
465 result="at least $2 args required, $1 given"
466 [[ $1 -lt $2 ]] && return
470 # num1 and num2 given
471 result="need at least $2 args, $1 given"
472 [[ $1 -lt $2 ]] && return
473 result="need at most $3 args, $1 given"
474 [[ $1 -gt $3 ]] && return