Merge branch 'maint'
[paraslash.git] / bash_completion
index aeee64c..7f1aecb 100644 (file)
-# Copyright (C) 2007 Andre Noll <maan@systemlinux.org>
+# Copyright (C) 2007-2014 Andre Noll <maan@tuebingen.mpg.de>
 #
 # Licensed under the GPL v2. For licencing details see COPYING.
 
-PC="para_client -l 5 -- "
-
-__para_commandlist=
-__para_sender_list=
-__para_table_list=
-__para_mood_list=
-__para_lyrics_list=
-__para_image_list=
-__para_playlist_list=
-__para_attributes_list=
-
-__paracomp()
-{
-        local cur="${COMP_WORDS[COMP_CWORD]}"
-        if [ $# -gt 2 ]; then
-                cur="$3"
-        fi
-        COMPREPLY=($(compgen -P "$2" -W "$1" -- "$cur"))
-}
-
-__para_complete_file()
-{
-       local cur="${COMP_WORDS[COMP_CWORD]}"
-       local sed_cmd="-e s|^\($cur[^/]\+/\).*|\1|1"
-       $PC ls -p -sp "${cur}*" | sed $sed_cmd | uniq
-}
-
-__para_complete_command()
-{
-       if test -z "$__para_command_list"; then
-               __para_command_list="$($PC help | cut -f 1)"
-       fi
-       echo "$__para_command_list"
-}
-
-__para_complete_table()
-{
-       if test -z "$__para_table_list"; then
-               __para_table_list="$(ls $HOME/.paraslash/afs_database/)"
-       fi
-       echo "$__para_table_list"
-}
-__para_complete_sender()
-{
-       if test -z "$__para_sender_list"; then
-               __para_sender_list="$($PC si | grep "supported senders:" | sed -e 's/.*: //')"
-       fi
-       echo "$__para_sender_list"
-}
-__para_complete_attribute()
-{
-       if test -z "$__para_attributes_list"; then
-               __para_attributes_list="$($PC lsatt)"
-       fi
-       echo "$__para_attributes_list"
-}
-__para_complete_playlist()
-{
-       if test -z "$__para_playlist_list"; then
-               __para_playlist_list="$($PC lspl)"
-       fi
-       echo "$__para_playlist_list"
-}
-__para_complete_mood()
-{
-       if test -z "$__para_mood_list"; then
-               __para_mood_list="$($PC lsmood)"
-       fi
-       echo "$__para_mood_list"
-}
-__para_complete_image()
+_para_complete()
 {
-       if test -z "$__para_image_list"; then
-               __para_image_list="$($PC lsimg)"
+       local prg="$1" # the program to execute
+       local cur=${COMP_WORDS[$COMP_CWORD]}
+       local line="$COMP_LINE" OLD_IFS="$IFS"
+       local opts n
+
+       if [[ "$COMP_WORDBREAKS" != ' '  ]]; then
+               COMP_WORDBREAKS=' '
+               return 124 # try again with proper value
        fi
-       echo "$__para_imagelist"
-}
-__para_complete_lyrics()
-{
-       if test -z "$__para_lyrics_list"; then
-               __para_lyrics_list="$($PC lslyr)"
+       # This extracts short and long options from the help output
+       local script='{
+               if ($1 ~ "-[a-zA-Z]," && $2 ~ "--[a-zA-Z]") {
+                       print substr($1, 0, 2);
+                       gsub("=.*", "", $2)
+                       print $2
+               } else if ($1 ~ "--[a-zA-Z]") {
+                       gsub("=.*", "", $1)
+                       print $1
+               }
+       }'
+
+       if [[ "$cur" == -* ]]; then # option
+               # Depending on whether '--' is one of the previous words we
+               # complete either on local options, i.e. those of the program
+               # to execute, or call the program to print possible completions
+               # (to a subcommand).
+               local_opts=true
+               for ((i=0; i < $COMP_CWORD; i++)); do
+                       [[ "${COMP_WORDS[$i]}" != '--' ]] && continue
+                       local_opts=false
+                       break
+               done
+               if [[ "$local_opts" == "true" ]]; then
+                       result="-- $($prg --help | awk "$script")"
+                       COMPREPLY=($(compgen -W "$result" -- $cur))
+                       return
+               fi
        fi
-       echo "$__para_lyrics_list"
-}
-
-__para_select()
-{
-       local cur="${COMP_WORDS[COMP_CWORD]}"
-       case "$cur" in
-       *)
-               __paracomp "$($PC lspl "${cur}*" | sed -e 's|^|p/|1') $($PC lsmood | sed -e 's|^|m/|1')"
-               ;;
-       esac
-}
-
-__para_setatt()
-{
-       local cur="${COMP_WORDS[COMP_CWORD]}"
-       if [ $COMP_CWORD -lt 3 ]; then
-               __paracomp "$(__para_complete_attribute)"
+       # We need to call the program with --complete to get the possible
+       # completions. Before that, all local options must be discarded.
+       IFS=' '
+       n=0
+       for word in $line; do
+               ((n > 0)) && ! [[ "$word" == -* ]] && break
+               line="${line##*( )}" # remove leading whitespace
+               line="${line##+([^ ])}"
+               line="${line##*( )}"
+               let n++
+               [[ "$word" == '--' ]] && break
+       done
+       IFS="$OLD_IFS"
+       s=$((${#COMP_LINE} - ${#line})) # how many characters have been cut
+       if (($COMP_POINT > $s)); then
+               COMP_POINT=$(($COMP_POINT - $s))
        else
-               if test -z "$cur" -o "$cur" = "${cur#/}"; then
-                       __paracomp "$(__para_complete_attribute)"
-               else
-                       __paracomp "$(__para_complete_file)"
-               fi
+               COMP_POINT=0
        fi
+       COMP_LINE="$line"
+       #echo "line: $COMP_LINE, point: $COMP_POINT"
+       export COMP_LINE COMP_POINT
+       result=($($prg --complete))
+
+       # the last line of the output contains the options for compopt,
+       # prefixed with '-o='.
+       n=${#result[@]}
+       (($n == 0)) && return # oops, $prg did not write any output
+       let n--
+       opts="${result[$n]}"
+       result[$n]=
+       opts="${opts#-o=}"
+       IFS=','
+       compopt +o nospace
+       for opt in $opts; do
+               #echo "opt: $opt"
+               case "$opt" in
+               filenames) compopt -o filenames;;
+               nospace) compopt -o nospace;;
+               esac
+       done
+       IFS="$OLD_IFS"
+       COMPREPLY=(${result[@]})
 }
 
-__para_sender()
+_para_audioc()
 {
-       if test $COMP_CWORD -eq 2; then
-               __paracomp "$(__para_complete_sender)"
-       elif test $COMP_CWORD -eq 3; then
-               __paracomp "on off add delete allow deny help"
-       else
-               COMPREPLY=()
-       fi
+       _para_complete para_audioc
 }
+complete -F _para_audioc para_audioc
 
 _para_client()
 {
-       local i c=1 command
-
-
-       while [ $c -lt $COMP_CWORD ]; do
-               i="${COMP_WORDS[c]}"
-               case "$i" in
-               --*) ;;
-               *) command="$i"; break ;;
-               esac
-               c=$((++c))
-       done
-
-       if [ $c -eq $COMP_CWORD ]; then
-               case "${COMP_WORDS[COMP_CWORD]}" in
-               --*=*) COMPREPLY=();;
-               *) __paracomp "$(__para_complete_command)";;
-               esac
-               return
-       fi
-
-       case "$command" in
-       stop|play|term|hup|pause|nomore|si|version) COMPREPLY=();;
-       setatt) __para_setatt;;
-       select) __para_select;;
-       touch|ls|rm|cpsi) __paracomp "$(__para_complete_file)";;
-       mvatt|lsatt|rmatt) __paracomp "$(__para_complete_attribute)";;
-       help) __paracomp "$(__para_complete_command)";;
-       sender) __para_sender;;
-       init) __paracomp __paracomp "$(__para_complete_table)";;
-       mvmood|lsmood|rmmood) __paracomp "$(__para_complete_mood)";;
-       mvlyr|lslyr|rmlyr) __paracomp "$(__para_complete_lyrics)";;
-       mvimg|lsimg|rmimg) __paracomp "$(__para_complete_image)";;
-       mvpl|lspl|rmpl) __paracomp "$(__para_complete_playlist)";;
-       esac
-
+       _para_complete para_client
 }
 complete -o default -o nospace -F _para_client para_client
 complete -o default -o nospace -F _para_client para
-