--- bash_completion~ 2007-01-21 23:58:23.000000000 +0100 +++ bash_completion 2007-01-21 23:55:44.000000000 +0100 @@ -3113,91 +3113,94 @@ complete -F _cd $nospace $filenames cd fi +# a wrapper method for the next one, when the offset is unknown +_command() +{ + local offset i + + # find actual offset, as position of the first non-option + offset=1 + for (( i=1; i <= COMP_CWORD; i++ )); do + if [[ "${COMP_WORDS[i]}" != -* ]]; then + offset=$i + break + fi + done + _command_offset $offset +} +complete -F _command $filenames nohup exec nice eval time ltrace then \ + else do vsound command xargs + # A meta-command completion function for commands like sudo(8), which need to # first complete on a command, then complete according to that command's own # completion definition - currently not quite foolproof (e.g. mount and umount # don't work properly), but still quite useful. # -_command() +_command_offset() { - local cur func cline cspec noglob cmd done i \ + local cur func cline cspec noglob cmd i offset \ _COMMAND_FUNC _COMMAND_FUNC_ARGS + offset=$1 + + # rewrite current completion context before invoking + # actual command completion + for (( i=0; i <= COMP_CWORD - $offset; i++ )); do + COMP_WORDS[i]=${COMP_WORDS[i+$offset]} + done + COMP_CWORD=$(($COMP_CWORD-$offset)) + COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} - # If the the first arguments following our meta-command-invoker are - # switches, get rid of them. Most definitely not foolproof. - done= - while [ -z $done ] ; do - cmd=${COMP_WORDS[1]} - if [[ "$cmd" == -* ]] ; then - for (( i=1 ; i<=COMP_CWORD ; i++)) ; do - COMP_WORDS[i]=${COMP_WORDS[i+1]} - done - COMP_CWORD=$(($COMP_CWORD-1)) - else - done=1 - fi - done - if [ $COMP_CWORD -eq 1 ]; then + if [ $COMP_CWORD -eq 0 ]; then COMPREPLY=( $( compgen -c -- $cur ) ) - elif complete -p $cmd &>/dev/null; then - cspec=$( complete -p $cmd ) - if [ "${cspec#* -F }" != "$cspec" ]; then - # complete -F <function> - # - # COMP_CWORD and COMP_WORDS() are not read-only, - # so we can set them before handing off to regular - # completion routine - - # set current token number to 1 less than now - COMP_CWORD=$(( $COMP_CWORD - 1 )) - - # get function name - func=${cspec#*-F } - func=${func%% *} - # get current command line minus initial command - cline="${COMP_LINE#*( )$1 }" - # save noglob state - shopt -qo noglob; noglob=$? - # turn on noglob, as things like 'sudo ls *<Tab>' - # don't work otherwise - shopt -so noglob - # split current command line tokens into array - COMP_WORDS=( $cline ) - # reset noglob if necessary - [ $noglob -eq 1 ] && shopt -uo noglob - $func $cline - # This is needed in case user finished entering - # command and pressed tab (e.g. sudo ls <Tab>) - COMP_CWORD=$(( $COMP_CWORD > 0 ? $COMP_CWORD : 1 )) - cur=${COMP_WORDS[COMP_CWORD]} - _COMMAND_FUNC=$func - _COMMAND_FUNC_ARGS=( $cmd $2 $3 ) - COMP_LINE=$cline - COMP_POINT=$(( ${COMP_POINT} - ${#1} - 1 )) - $func $cmd $2 $3 - # remove any \: generated by a command that doesn't - # default to filenames or dirnames (e.g. sudo chown) - if [ "${cspec#*-o }" != "$cspec" ]; then - cspec=${cspec#*-o } - cspec=${cspec%% *} - if [[ "$cspec" != @(dir|file)names ]]; then - COMPREPLY=("${COMPREPLY[@]//\\\\:/:}") + else + cmd=${COMP_WORDS[0]} + if complete -p $cmd &>/dev/null; then + cspec=$( complete -p $cmd ) + if [ "${cspec#* -F }" != "$cspec" ]; then + # complete -F <function> + + # get function name + func=${cspec#*-F } + func=${func%% *} + # save noglob state + shopt -qo noglob; noglob=$? + # turn on noglob, as things like + # 'sudo ls *<Tab>' don't work otherwise + shopt -so noglob + # reset noglob if necessary + [ $noglob -eq 1 ] && shopt -uo noglob + # This is needed in case user finished entering + # command and pressed tab (e.g. sudo ls <Tab>) + COMP_CWORD=$(( $COMP_CWORD > 0 ? $COMP_CWORD : 1 )) + cur=${COMP_WORDS[COMP_CWORD]} + _COMMAND_FUNC=$func + _COMMAND_FUNC_ARGS=( $cmd $2 $3 ) + COMP_LINE=$cline + COMP_POINT=$(( ${COMP_POINT} - ${#1} - 1 )) + $func $cmd $2 $3 + # remove any \: generated by a command that + # doesn't default to filenames or dirnames + # (e.g. sudo chown) + if [ "${cspec#*-o }" != "$cspec" ]; then + cspec=${cspec#*-o } + cspec=${cspec%% *} + if [[ "$cspec" != @(dir|file)names ]]; then + COMPREPLY=("${COMPREPLY[@]//\\\\:/:}") + fi fi + elif [ -n "$cspec" ]; then + cspec=${cspec#complete}; + cspec=${cspec%%$cmd}; + COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) ); fi - elif [ -n "$cspec" ]; then - cspec=${cspec#complete}; - cspec=${cspec%%$cmd}; - COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) ); + else + _filedir fi fi - - [ ${#COMPREPLY[@]} -eq 0 ] && _filedir } -complete -F _command $filenames nohup exec nice eval strace time ltrace then \ - else do vsound command xargs _root_command() {