+
+_com_complete()
+{
+ local cmd n cword
+ local -a words
+
+ if (($# == 0)); then
+ cat <<EOF
+ local cur="\${COMP_WORDS[\$COMP_CWORD]}";
+ local -a candidates;
+
+ candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}"));
+ COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur"));
+EOF
+ ret=$GSU_SUCCESS
+ return
+ fi
+
+ cword="$1"
+ gsu_is_a_number "$cword"
+ (($ret < 0)) && return
+ if (($cword <= 1)); then
+ _gsu_available_commands
+ echo "${result}"
+ ret=$GSU_SUCCESS
+ return
+ fi
+ shift
+ words=("$@")
+ cmd="${words[1]}"
+ ret=$GSU_SUCCESS # It's not an error if no completer was defined
+ [[ "$(type -t complete_$cmd)" != "function" ]] && return
+ complete_$cmd "$cword" "${words[@]}"
+ # ignore errors, they would only clutter the completion output
+ ret=$GSU_SUCCESS
+}
+
+# Find out if the current word is a parameter for an option.
+#
+# $1: usual getopts option string.
+# $2: The current word number.
+# $3..: All words of the current command line.
+#
+# return: If yes, $result contains the letter of the option for which the
+# current word is a parameter. Otherwise, $result is empty.
+#
+gsu_cword_is_option_parameter()
+{
+ local opts="$1" cword="$2" prev i n
+ local -a words
+
+ result=
+ (($cword == 0)) && return
+ ((${#opts} < 2)) && return
+
+ shift 2
+ words=("$@")
+ prev="${words[$(($cword - 1))]}"
+ [[ ! "$prev" == -* ]] && return
+
+ n=$((${#opts} - 1))
+ for ((i=0; i <= $n; i++)); do
+ opt="${opts:$i:1}"
+ [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue
+ let i++
+ [[ "$prev" != "-$opt" ]] && continue
+ result="$opt"
+ return
+ done
+ ret=0
+}