]> 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="$({
 _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' ' ')"
 }
                sed -ne "s/$gsu_command_regex/\1/g;T;p" $0
                } | sort | tr '\n' ' ')"
 }
@@ -43,6 +43,26 @@ _gsu_print_available_commands()
 ) 2>&1
 }
 
 ) 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.
 
 export gsu_prefs_txt="
 Print the current preferences.
 
@@ -93,6 +113,11 @@ _com_prefs()
        done
 }
 
        done
 }
 
+complete_prefs()
+{
+       gsu_complete_options "e" "$@"
+}
+
 export gsu_man_txt="
 Print the manual.
 
 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."
 
 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
 _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_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" \
                        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
                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
        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
 }
 
        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
 # 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
 }
 
        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
 gsu()
 {
        local i
@@ -310,7 +417,7 @@ gsu()
        arg="$1"
        shift
        # check internal commands
        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
                _com_$arg "$@"
                if [[ "$ret" -lt 0 ]]; then
                        gsu_err_msg