]> git.tuebingen.mpg.de Git - gsu.git/blobdiff - misc/gsu/subcommand
gsu: Initial completion support.
[gsu.git] / misc / gsu / subcommand
index f09c66de613707c42794947e8b0b787c79f11f5e..f5f4745a8856920a0203b02039eadce46f4bf2ef 100644 (file)
@@ -18,7 +18,7 @@ export gsu_command_regex='^com_\([-a-zA-Z_0-9]\+\)()'
 _gsu_available_commands()
 {
        result="$({
-               printf "help\nman\nprefs\n"
+               printf "help\nman\nprefs\ncomplete\n"
                sed -ne "s/$gsu_command_regex/\1/g;T;p" $0
                } | sort | tr '\n' ' ')"
 }
@@ -43,6 +43,26 @@ _gsu_print_available_commands()
 ) 2>&1
 }
 
+gsu_complete_options()
+{
+       local opts="$1" cword="$2" cur
+       local -a words
+
+       shift 2
+       words=("$@")
+       cur="${words[$cword]}"
+       ret=0
+       [[ ! "$cur" == -* ]] && return
+
+       ret=0
+       for ((i=0; i < ${#opts}; i++)); do
+               opt="${opts:$i:1}"
+               [[ "$opt" == ":" ]] && continue
+               printf "%s" "-$opt "
+               let ret++
+       done
+}
+
 export gsu_prefs_txt="
 Print the current preferences.
 
@@ -93,6 +113,11 @@ _com_prefs()
        done
 }
 
+complete_prefs()
+{
+       gsu_complete_options "e" "$@"
+}
+
 export gsu_man_txt="
 Print the manual.
 
@@ -155,6 +180,18 @@ Usage: help [command]
 Without arguments, print the list of available commands. Otherwise,
 print the help text for the given command."
 
+export gsu_complete_txt="
+Command line completion.
+
+Usage: complete [<cword> <word>...]
+
+In the first form, the command prints all possible completions to stdout.
+This can be used from the completion function of the shell.
+
+Completion code suitable to be evaled is written to stdout if no argument
+was given.
+"
+
 _com_help()
 {
        local a b
@@ -165,6 +202,7 @@ _com_help()
                        printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
                        printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
                        printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
+                       printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
                        grep -A 2 "$gsu_command_regex" $0
                } | grep -v -- '--' \
                        | sed -e "/$gsu_command_regex/bs" \
@@ -200,6 +238,11 @@ _com_help()
                ret=$GSU_SUCCESS
                return
        fi
+       if test "$1" = "complete"; then
+               echo "$gsu_complete_txt"
+               ret=$GSU_SUCCESS
+               return
+       fi
        ret=$GSU_SUCCESS
        if grep -q "^com_$1()" $0; then
                sed -e "1,/^com_$1()$/d" -e '/^{/,$d' -e 's/^## *//' $0
@@ -210,6 +253,12 @@ _com_help()
        ret=-$E_GSU_BAD_COMMAND
 }
 
+complete_help()
+{
+       _gsu_available_commands
+       echo "$result"
+}
+
 # Wrapper for bash's getopts.
 #
 # Aborts on programming errors such as missing or invalid option string.  On
@@ -296,6 +345,64 @@ gsu_getopts()
        ret=$GSU_SUCCESS
 }
 
+_com_complete()
+{
+       local cmd n cword="$1"
+       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
+       fi
+
+       [[ -z "$cword" ]] && 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
+}
+
+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
+}
+
 gsu()
 {
        local i
@@ -310,7 +417,7 @@ gsu()
        arg="$1"
        shift
        # check internal commands
-       if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" ]]; then
+       if [[ "$arg" = "help" || "$arg" = "man" || "$arg" = "prefs" || "$arg" = "complete" ]]; then
                _com_$arg "$@"
                if [[ "$ret" -lt 0 ]]; then
                        gsu_err_msg