[Bash-completion-commits] [SCM] bash-completion branch, master, updated. 94372b2aa6e9df90d47bedb1dabedb3a71ee1e0e

Freddy Vulto fvulto at gmail.com
Thu Jun 10 21:53:39 UTC 2010


The following commit has been merged in the master branch:
commit 94372b2aa6e9df90d47bedb1dabedb3a71ee1e0e
Merge: 1322b88cecf1859d560d6389de70d23f7d09d8bf 0118ccb05a4cb583765780d561201d13a56863d9
Author: Freddy Vulto <fvulto at gmail.com>
Date:   Thu Jun 10 23:51:30 2010 +0200

    Merge branch 'use-_get_comp_words_by_ref'

diff --combined bash_completion
index 1573d03,fa9c7e4..7a727f9
--- a/bash_completion
+++ b/bash_completion
@@@ -1,5 -1,5 +1,5 @@@
  #
 -#   bash_completion - programmable completion functions for bash 3.x
 +#   bash_completion - programmable completion functions for bash 3.2+
  #
  #   Copyright © 2006-2008, Ian Macdonald <ian at caliban.org>
  #             © 2009-2010, Bash Completion Maintainers
@@@ -70,10 -70,10 +70,10 @@@ complete -d push
  # START exclude -- do NOT remove this line
  # bzcmp, bzdiff, bz*grep, bzless, bzmore intentionally not here, see Debian: #455510
  complete -f -X '!*.?(t)bz?(2)' bunzip2 bzcat pbunzip2 pbzcat
 -complete -f -X '!*.@(zip|ZIP|jar|JAR|exe|EXE|pk3|war|wsz|ear|zargo|xpi|sxw|ott|od[fgpst]|epub)' unzip zipinfo
 +complete -f -X '!*.@(zip|ZIP|[ejw]ar|[EJW]AR|exe|EXE|pk3|wsz|zargo|xpi|sxw|o[tx]t|od[fgpst]|epub)' unzip zipinfo
  complete -f -X '*.Z' compress znew
  # zcmp, zdiff, z*grep, zless, zmore intentionally not here, see Debian: #455510
 -complete -f -X '!*.@(Z|gz|tgz|Gz|dz)' gunzip zcat unpigz
 +complete -f -X '!*.@(Z|[gGd]z|t[ag]z)' gunzip zcat unpigz
  complete -f -X '!*.Z' uncompress
  # lzcmp, lzdiff intentionally not here, see Debian: #455510
  complete -f -X '!*.lzma' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma
@@@ -90,9 -90,9 +90,9 @@@ complete -f -X '!*.@(@(?(e)ps|?(E)PS|pd
  complete -f -X '!*.@(okular|@(?(e|x)ps|?(E|X)PS|pdf|PDF|dvi|DVI|cb[rz]|CB[RZ]|djv?(u)|DJV?(U)|dvi|DVI|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX|epub|EPUB|odt|ODT|fb|FB|mobi|MOBI|g3|G3|chm|CHM|fdf|FDF)?(.?(gz|GZ|bz2|BZ2)))' okular
  complete -f -X '!*.@(?(e)ps|?(E)PS|pdf|PDF)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr
  complete -f -X '!*.texi*' makeinfo texi2html
 -complete -f -X '!*.@(?(la)tex|?(LA)TEX|texi|TEXI|dtx|DTX|ins|INS)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi
 +complete -f -X '!*.@(?(la)tex|?(LA)TEX|texi|TEXI|dtx|DTX|ins|INS|ltx|LTX)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi
  complete -f -X '!*.@(mp3|MP3)' mpg123 mpg321 madplay
 -complete -f -X '!*@(.@(mp?(e)g|MP?(E)G|wma|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|viv|rm|ram|yuv|mov|MOV|qt|QT|wmv|mp[234]|MP[234]|m4[pv]|M4[PV]|mkv|MKV|og[gmv]|OG[GMV]|wav|WAV|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))' xine aaxine fbxine kaffeine dragon
 +complete -f -X '!*@(.@(mp?(e)g|MP?(E)G|wma|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|wmv|mp[234]|MP[234]|m4[pv]|M4[PV]|mkv|MKV|og[gmv]|OG[GMV]|t[ps]|T[PS]|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))' xine aaxine fbxine kaffeine dragon
  complete -f -X '!*.@(avi|asf|wmv)' aviplay
  complete -f -X '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay
  complete -f -X '!*.@(mpg|mpeg|avi|mov|qt)' xanim
@@@ -101,12 -101,13 +101,12 @@@ complete -f -X '!*.@(mp3|MP3|ogg|OGG|pl
  complete -f -X '!*.fig' xfig
  complete -f -X '!*.@(mid?(i)|MID?(I)|cmf|CMF)' playmidi
  complete -f -X '!*.@(mid?(i)|MID?(I)|rmi|RMI|rcp|RCP|[gr]36|[GR]36|g18|G18|mod|MOD|xm|XM|it|IT|x3m|X3M|s[3t]m|S[3T]M|kar|KAR)' timidity
 -complete -f -X '!*.@(m[eo]d|M[EO]D|s[3t]m|S[3T]M|xm|XM|it|IT)' modplugplay
 -complete -f -X '*.@(o|so|so.!(conf)|a|rpm|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MPG|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)' vi vim gvim rvim view rview rgvim rgview gview
 -complete -f -X '*.@(o|so|so.!(conf)|a|rpm|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MPG|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)' emacs
 -complete -f -X '!*.@(exe|EXE|com|COM|scr|SCR|exe.so)' wine
 +complete -f -X '!*.@(m[eo]d|M[EO]D|s[3t]m|S[3T]M|xm|XM|it|IT)' modplugplay modplug123
 +complete -f -X '*.@(o|so|so.!(conf)|a|rpm|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MPG|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite
 +complete -f -X '!*.@([eE][xX][eE]?(.[sS][oO])|[cC][oO][mM]|[sS][cC][rR])' wine
  complete -f -X '!*.@(zip|ZIP|z|Z|gz|GZ|tgz|TGZ)' bzme
  # konqueror not here on purpose, it's more than a web/html browser
 -complete -f -X '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx opera galeon curl dillo elinks amaya firefox mozilla-firefox iceweasel google-chrome chromium-browser epiphany
 +complete -f -X '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx opera galeon dillo elinks amaya firefox mozilla-firefox iceweasel google-chrome chromium-browser epiphany
  complete -f -X '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|odt|ott|odm)' oowriter
  complete -f -X '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|odp|otp)' ooimpress
  complete -f -X '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|ods|ots)' oocalc
@@@ -114,15 -115,12 +114,15 @@@ complete -f -X '!*.@(sxd|std|sda|sdd|od
  complete -f -X '!*.@(sxm|smf|mml|odf)' oomath
  complete -f -X '!*.odb' oobase
  complete -f -X '!*.rpm' rpm2cpio
 -complete -f -X '!*.sqlite' sqlite3
 +complete -f -X '!*.s@(qlite?(3)|?(3)db)' sqlite3
  complete -f -X '!*.aux' bibtex
  complete -f -X '!*.po' poedit gtranslator kbabel lokalize
  complete -f -X '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp
  complete -f -X '!*.[Hh][Rr][Bb]' hbrun
  complete -f -X '!*.ly' lilypond ly2dvi
 +complete -f -X '!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))' cdiff
 +complete -f -X '!*.@(dif?(f)|?(d)patch)' kompare
 +complete -f -X '!*.lyx' lyx
  # FINISH exclude -- do not remove this line
  
  # start of section containing compspecs that can be handled within bash
@@@ -168,8 -166,6 +168,8 @@@ complete -b builti
  have()
  {
      unset -v have
 +    # Completions for system administrator commands are installed as well in
 +    # case completion is attempted via `sudo command ...'.
      PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 &>/dev/null &&
      have="yes"
  }
@@@ -204,6 -200,68 +204,68 @@@ dequote(
  }
  
  
+ # Assign variable one scope above the caller
+ # Usage: local "$1" && _upvar $1 "value(s)"
+ # Param: $1  Variable name to assign value to
+ # Param: $*  Value(s) to assign.  If multiple values, an array is
+ #            assigned, otherwise a single value is assigned.
+ # NOTE: For assigning multiple variables, use '_upvars'.  Do NOT
+ #       use multiple '_upvar' calls, since one '_upvar' call might
+ #       reassign a variable to be used by another '_upvar' call.
+ # See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
+ _upvar() {
+     if unset -v "$1"; then           # Unset & validate varname
+         if (( $# == 2 )); then
+             eval $1=\"\$2\"          # Return single value
+         else
+             eval $1=\(\"\${@:2}\"\)  # Return array
+         fi
+     fi
+ }
+ 
+ 
+ # Assign variables one scope above the caller
+ # Usage: local varname [varname ...] && 
+ #        _upvars [-v varname value] | [-aN varname [value ...]] ...
+ # Available OPTIONS:
+ #     -aN  Assign next N values to varname as array
+ #     -v   Assign single value to varname
+ # Return: 1 if error occurs
+ # See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
+ _upvars() {
+     if ! (( $# )); then
+         echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
+             "value] | [-aN varname [value ...]] ..." 1>&2
+         return 2
+     fi
+     while (( $# )); do
+         case $1 in
+             -a*)
+                 # Error checking
+                 [[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1': missing"\
+                     "number specifier" 1>&2; return 1; }
+                 printf %d "${1#-a}" &> /dev/null || { echo "bash:"\
+                     "${FUNCNAME[0]}: \`$1': invalid number specifier" 1>&2
+                     return 1; }
+                 # Assign array of -aN elements
+                 [[ "$2" ]] && unset -v "$2" && eval $2=\(\"\${@:3:${1#-a}}\"\) && 
+                 shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:"\
+                     "\`$1${2+ }$2': missing argument(s)" 1>&2; return 1; }
+                 ;;
+             -v)
+                 # Assign single value
+                 [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
+                 shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\
+                 "argument(s)" 1>&2; return 1; }
+                 ;;
+             *)
+                 echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2
+                 return 1 ;;
+         esac
+     done
+ }
+ 
+ 
  # Reassemble command line words, excluding specified characters from the
  # list of word completion separators (COMP_WORDBREAKS).
  # @param $1 chars  Characters out of $COMP_WORDBREAKS which should
@@@ -267,30 -325,10 +329,10 @@@ __reassemble_comp_words_by_ref() 
  # @param $4 cur  Name of variable to return current word to complete to
  # @see ___get_cword_at_cursor_by_ref()
  __get_cword_at_cursor_by_ref() {
-     # NOTE: The call to the main function ___get_cword_at_cursor_by_ref() is
-     #       wrapped to make collisions with local variable names less likely.
-     local __words __cword __cur
-     ___get_cword_at_cursor_by_ref "$1" __words __cword __cur
- 
-     eval $2=\( \"\${__words[@]}\" \)
-     eval $3=\$__cword
-     eval $4=\$__cur
- }
- 
- 
- # @param $1 exclude
- # @param $2 words  Name of variable to return words to
- # @param $3 cword  Name of variable to return cword to
- # @param $4 cur  Name of variable to return current word to complete to
- # @note  Do not call this function directly but call 
- #     `__get_cword_at_cursor_by_ref()' instead to make variable name collisions
- #     less likely
- # @see __get_cword_at_cursor_by_ref()
- ___get_cword_at_cursor_by_ref() {
-     local cword words
+     local cword words=()
      __reassemble_comp_words_by_ref "$1" words cword
  
-     local i
+     local i cur2
      local cur="$COMP_LINE"
      local index="$COMP_POINT"
      for (( i = 0; i <= cword; ++i )); do
@@@ -318,13 -356,13 +360,13 @@@
  
      if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
          # We messed up. At least return the whole word so things keep working
-         eval $4=\"\${words[cword]}\"
+         cur2=${words[cword]}
      else
-         eval $4=\"\${cur:0:\$index}\"
+         cur2=${cur:0:$index}
      fi
  
-     eval $2=\( \"\${words[@]}\" \)
-     eval $3=\$cword
+     local "$2" "$3" "$4" && 
+         _upvars -a${#words[@]} $2 "${words[@]}" -v $3 "$cword" -v $4 "$cur2"
  }
  
  
@@@ -334,62 -372,66 +376,66 @@@
  # (For example, if the line is "ls foobar",
  # and the cursor is here -------->   ^
  # Also one is able to cross over possible wordbreak characters.
- # Usage: _get_comp_words_by_ref [OPTIONS] VAR1 [VAR2 [VAR3]]
+ # Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
+ # Available VARNAMES:
+ #     cur         Return cur via $cur
+ #     prev        Return prev via $prev
+ #     words       Return words via $words
+ #     cword       Return cword via $cword
+ #
+ # Available OPTIONS:
+ #     -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT be 
+ #                 considered word breaks. This is useful for things like scp
+ #                 where we want to return host:path and not only path, so we
+ #                 would pass the colon (:) as -n option in this case.  Bash-3
+ #                 doesn't do word splitting, so this ensures we get the same
+ #                 word on both bash-3 and bash-4.
+ #     -c VARNAME  Return cur via $VARNAME
+ #     -p VARNAME  Return prev via $VARNAME
+ #     -w VARNAME  Return words via $VARNAME
+ #     -i VARNAME  Return cword via $VARNAME
+ #
  # Example usage:
  #
  #    $ _get_comp_words_by_ref -n : cur prev
  #
- # Options:  -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT
- #     be considered word breaks. This is useful for things like scp where
- #     we want to return host:path and not only path, so we would pass the
- #     colon (:) as -n option in this case.  Bash-3 doesn't do word splitting,
- #     so this ensures we get the same word on both bash-3 and bash-4.
- # @see __get_comp_words_by_ref
- _get_comp_words_by_ref() {
-     # NOTE: The call to the main function __get_comp_words_by_ref() is wrapped
-     #       to make collisions with local variable name less likely.
-     local __words __cword __cur __var __vars 
-     __get_comp_words_by_ref __words __cword __cur __vars "$@"
-     set -- "${__vars[@]}"
-     eval $1=\$__cur
-     shift
-     for __var; do
-         ((__cword--))
-         [[ ${__words[__cword]} ]] && eval $__var=\${__words[__cword]}
-     done
- }
- 
- 
- # @param $1 words  Name of variable to return words to
- # @param $2 cword  Name of variable to return cword to
- # @param $3 cur  Name of variable to return current word to complete to
- # @param $4 varnames  Name of variable to return array of variable names to
- # @param $@  Arguments to _get_comp_words_by_ref()
- # @note  Do not call this function directly but call `_get_comp_words_by_ref()'
- #     instead to make variable name collisions less likely
- # @see _get_comp_words_by_ref()
- __get_comp_words_by_ref()
+ _get_comp_words_by_ref()
  {
-     local exclude flag i OPTIND=5  # Skip first four arguments
-     local cword words cur varnames=()
-     while getopts "n:" flag "$@"; do
+     local exclude flag i OPTIND=1
+     local cur cword words=()
+     local upargs=() upvars=() vcur vcword vprev vwords
+ 
+     while getopts "c:i:n:p:w:" flag "$@"; do
          case $flag in
+             c) vcur=$OPTARG ;;
+             i) vcword=$OPTARG ;;
              n) exclude=$OPTARG ;;
+             p) vprev=$OPTARG ;;
+             w) vwords=$OPTARG ;;
          esac
      done
-     varnames=( ${!OPTIND} )
-     let "OPTIND += 1"
      while [[ $# -ge $OPTIND ]]; do 
-         varnames+=( ${!OPTIND} )
+         case ${!OPTIND} in
+             cur)   vcur=cur ;;
+             prev)  vprev=prev ;;
+             cword) vcword=cword ;;
+             words) vwords=words ;;
+             *) echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" \
+                 1>&2; return 1
+         esac
          let "OPTIND += 1"
      done
  
      __get_cword_at_cursor_by_ref "$exclude" words cword cur
  
-     eval $1=\( \"\${words[@]}\" \)
-     eval $2=\$cword
-     eval $3=\$cur
-     eval $4=\( \"\${varnames[@]}\" \)
+     [[ $vcur   ]] && { upvars+=("$vcur"  ); upargs+=(-v $vcur   "$cur"  ); }
+     [[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
+     [[ $vprev  ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev 
+         "${words[cword - 1]}"); }
+     [[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
+         "${words[@]}"); }
+ 
+     (( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
  }
  
  
@@@ -407,10 -449,10 +453,11 @@@
  #     current word (default is 0, previous is 1), respecting the exclusions
  #     given at $1.  For example, `_get_cword "=:" 1' returns the word left of
  #     the current word, respecting the exclusions "=:".
- #
+ # @deprecated  Use `_get_comp_words_by_ref cur' instead
+ # @see _get_comp_words_by_ref()
  _get_cword()
  {
 +    local LC_CTYPE=C
      local cword words
      __reassemble_comp_words_by_ref "$1" words cword
  
@@@ -461,7 -503,8 +508,8 @@@
  # This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4
  # will properly return the previous word with respect to any given exclusions to
  # COMP_WORDBREAKS.
- # @see _get_cword()
+ # @deprecated  Use `_get_comp_words_by_ref cur prev' instead
+ # @see _get_comp_words_by_ref()
  #
  _get_pword() 
  {
@@@ -525,6 -568,14 +573,6 @@@ __ltrim_colon_completions() 
  # @param $2  Name of variable to return result to
  _quote_readline_by_ref()
  {
 -   # If bash <= 3 and argument starts with single quote ('), double-escape
 -#   if [[ ${BASH_VERSINFO[0]} -le 3 && ${1:0:1} == "'" ]]; then
 -#        local t
 -#        printf -v t %q "${1:1}"
 -#        printf -v $2 %q "$t"
 -#   else
 -#        printf -v $2 %q "$1"
 -#   fi
      if [[ ${1:0:1} == "'" ]]; then
          # Quote word, leaving out first character
          printf -v $2 %q "${1:1}"
@@@ -537,18 -588,13 +585,18 @@@
      else
          printf -v $2 %q "$1"
      fi
 +
 +    # If result becomes quoted like this: $'string', re-evaluate in order to
 +    # drop the additional quoting.  See also: http://www.mail-archive.com/
 +    # bash-completion-devel at lists.alioth.debian.org/msg01942.html
 +    [[ ${!2:0:1} == '$' ]] && eval $2=${!2}
  } # _quote_readline_by_ref()
  
  
  # This function performs file and directory completion. It's better than
  # simply using 'compgen -f', because it honours spaces in filenames.
 -# If passed -d, it completes only on directories. If passed anything else,
 -# it's assumed to be a file glob to complete on.
 +# @param $1  If `-d', complete only on directories.  Otherwise filter/pick only
 +#            completions with `.$1' as file extension.
  #
  _filedir()
  {
@@@ -559,15 -605,20 +607,15 @@@
      local -a toks
      local quoted tmp
  
 -    # TODO: I've removed a "[ -n $tmp ] &&" before `printf '%s\n' $tmp',
 -    #       and everything works again. If this bug
 -    #       suddenly appears again (i.e. "cd /b<TAB>"
 -    #       becomes "cd /"), remember to check for
 -    #       other similar conditionals (here and
 -    #       _filedir_xspec()). --David
 -    # NOTE: The comment above has been moved outside of the subshell below,
 -    #       because quotes-in-comments-in-a-subshell cause errors on
 -    #       bash-3.1.  See also:
 -    #       http://www.mail-archive.com/bug-bash@gnu.org/msg01667.html
      _quote_readline_by_ref "$cur" quoted
      toks=( ${toks[@]-} $(
          compgen -d -- "$quoted" | {
              while read -r tmp; do
 +                # TODO: I have removed a "[ -n $tmp ] &&" before 'printf ..',
 +                #       and everything works again. If this bug suddenly
 +                #       appears again (i.e. "cd /b<TAB>" becomes "cd /"),
 +                #       remember to check for other similar conditionals (here
 +                #       and _filedir_xspec()). --David
                  printf '%s\n' $tmp
              done
          }
@@@ -599,22 -650,17 +647,22 @@@
              compopt &>/dev/null && compopt -o filenames ||
              # No, `compopt' isn't available;
              # Is `-o filenames' set?
 -            [[ "$(complete -p ${COMP_WORDS[0]})" == *"-o filenames"* ]] || {
 +            [[ (
 +                ${COMP_WORDS[0]} && 
 +                "$(complete -p ${COMP_WORDS[0]})" == *"-o filenames"*
 +            ) ]] || {
                  # No, `-o filenames' isn't set;
                  # Emulate `-o filenames'
 -                # NOTE: A side-effect of emulating `-o filenames' is that backslash escape
 -                #       characters are visible within the list of presented completions, e.g.
 -                #       the completions look like:
 +                # NOTE: A side-effect of emulating `-o filenames' is that
 +                #       backslash escape characters are visible within the list
 +                #       of presented completions, e.g.  the completions look
 +                #       like:
                  #
                  #           $ foo a<TAB>
                  #           a\ b/  a\$b/
                  #
 -                #       whereas with `-o filenames' active the completions look like:
 +                #       whereas with `-o filenames' active the completions look
 +                #       like:
                  #
                  #           $ ls a<TAB>
                  #           a b/  a$b/
@@@ -624,11 -670,11 +672,11 @@@
                      if [[ ${cur:0:1} != "'" ]]; then
                          [[ -d ${toks[i]} ]] && toks[i]="${toks[i]}"/
                          if [[ ${cur:0:1} == '"' ]]; then
 -                            toks[i]=${toks[i]//\\/\\\\}       
 +                            toks[i]=${toks[i]//\\/\\\\}
                              toks[i]=${toks[i]//\"/\\\"}
                              toks[i]=${toks[i]//\$/\\\$}
                          else
 -                            toks[i]=$(printf %q ${toks[i]})       
 +                            toks[i]=$(printf %q ${toks[i]})
                          fi
                      fi
                  done
@@@ -682,26 -728,6 +730,26 @@@ _signals(
      done
  }
  
 +# This function completes on known mac addresses
 +#
 +_mac_addresses()
 +{
 +    local re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}'
 +    local PATH="$PATH:/sbin:/usr/sbin"
 +
 +    # Local interfaces (Linux only?)
 +    COMPREPLY=( "${COMPREPLY[@]}" $( ifconfig -a 2>/dev/null | sed -ne \
 +        "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" ) )
 +
 +    # ARP cache
 +    COMPREPLY=( "${COMPREPLY[@]}" $( arp -an 2>/dev/null | sed -ne \
 +        "s/.*[[:space:]]\($re\)[[:space:]].*/\1/p" -ne \
 +        "s/.*[[:space:]]\($re\)[[:space:]]*$/\1/p" ) )
 +
 +    COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) )
 +    __ltrim_colon_completions "$cur"
 +}
 +
  # This function completes on configured network interfaces
  #
  _configured_interfaces()
@@@ -786,7 -812,7 +834,7 @@@ __expand_tilde_by_ref() 
              #    becomes "~a".  Double quotes allow eval.
              # 2: Remove * before the first slash (/), i.e. "~a/b"
              #    becomes "b".  Single quotes prevent eval.
-             #       +-----1----+ +---2----+
+             #                          +-----1----+ +---2----+
              eval $1="${!1/%\/*}"/'${!1#*/}'
          else 
              # No, $1 doesn't contain slash
@@@ -846,8 -872,8 +894,8 @@@ _pgids(
  [[ $UNAME == SunOS || $UNAME == AIX ]] &&
  _pnames()
  {
 -    COMPREPLY=( $( compgen -W '$( command ps -efo comm | \
 -        sed -e 1d -e "s:.*/::" -e "s/^-//" -e "s/^<defunct>$//")' -- "$cur" ) )
 +    COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps -efo comm | \
 +        sed -e 1d -e "s:.*/::" -e "s/^-//" | sort -u )' -- "$cur" ) )
  } ||
  _pnames()
  {
@@@ -859,9 -885,9 +907,9 @@@
      # for now.
      # Not using "ps axo comm" because under some Linux kernels, it
      # truncates command names (see e.g. http://bugs.debian.org/497540#19)
 -    COMPREPLY=( $( compgen -W '$( command ps axo command= | \
 +    COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps axo command= | \
          sed -e "s/ .*//" -e "s:.*/::" -e "s/:$//" -e "s/^[[(-]//" \
 -            -e "s/[])]$//" -e "s/^<defunct>$//")' -- "$cur" ) )
 +            -e "s/[])]$//" | sort -u )' -- "$cur" ) )
  }
  
  # This function completes on user IDs
@@@ -973,36 -999,12 +1021,36 @@@ _shells(
          -- "$cur" ) )
  }
  
 +# This function completes on valid filesystem types
 +#
 +_fstypes()
 +{
 +    local fss
 +
 +    if [ -e /proc/filesystems ] ; then
 +        # Linux
 +        fss="$( cut -d$'\t' -f2 /proc/filesystems )
 +             $( awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null )"
 +    else
 +        # Generic
 +        fss="$( awk '/^[ \t]*[^#]/ { print $3 }' /etc/fstab 2>/dev/null )
 +             $( awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null )
 +             $( awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null )
 +             $( awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null )
 +             $( [ -d /etc/fs ] && command ls /etc/fs )"
 +    fi
 +
 +    [ -n "$fss" ] && \
 +        COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$fss" -- "$cur" ) )
 +}
 +
  # Get real command.
  # - arg: $1  Command
  # - stdout:  Filename of command in PATH with possible symbolic links resolved.
  #            Empty string if command not found.
  # - return:  True (0) if command found, False (> 0) if not.
 -_realcommand() {
 +_realcommand()
 +{
      type -P "$1" > /dev/null && {
          if type -p realpath > /dev/null; then
              realpath "$(type -P "$1")"
@@@ -1014,24 -1016,8 +1062,24 @@@
      }
  }
  
 +# This function returns the first arugment, excluding options
 +# @param $1 chars  Characters out of $COMP_WORDBREAKS which should
 +#     NOT be considered word breaks. See __reassemble_comp_words_by_ref.
 +_get_first_arg()
 +{
 +    local i
  
 -# This function counts the number of args
 +    arg=
 +    for (( i=1; i < COMP_CWORD; i++ )); do
 +        if [[ "${COMP_WORDS[i]}" != -* ]]; then
 +            arg=${COMP_WORDS[i]}
 +            break
 +        fi
 +    done
 +}
 +
 +
 +# This function counts the number of args, excluding options
  # @param $1 chars  Characters out of $COMP_WORDBREAKS which should
  #     NOT be considered word breaks. See __reassemble_comp_words_by_ref.
  _count_args()
@@@ -1082,13 -1068,341 +1130,13 @@@ _dvd_devices(
      patch configure build install reinstall deinstall clean clean-depends \
      kernel buildworld' make
  
 -# This completes on a list of all available service scripts for the
 -# 'service' command and/or the SysV init.d directory, followed by
 -# that script's available commands
 -#
 -{ have service || [ -d /etc/init.d/ ]; } &&
 -_service()
 -{
 -    local cur prev sysvdir
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur prev
 -
 -    # don't complete for things like killall, ssh and mysql if it's
 -    # the standalone command, rather than the init script
 -    [[ ${COMP_WORDS[0]} != @(*init.d/!(functions|~)|service) ]] && return 0
 -
 -    # don't complete past 2nd token
 -    [ $COMP_CWORD -gt 2 ] && return 0
 -
 -    [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d || sysvdir=/etc/init.d
 -
 -    if [[ $COMP_CWORD -eq 1 ]] && [[ $prev == "service" ]]; then
 -        _services
 -    else
 -        COMPREPLY=( $( compgen -W '`sed -e "y/|/ /" \
 -            -ne "s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \
 -            $sysvdir/${prev##*/} 2>/dev/null`' -- "$cur" ) )
 -    fi
 -
 -    return 0
 -} &&
 -complete -F _service service
 -[ -d /etc/init.d/ ] && complete -F _service -o default \
 -    $(for i in /etc/init.d/*; do printf '%s\n' ${i##*/}; done)
 -
 -
 -# chown(1) completion
 -#
 -_chown()
 -{
 -    local cur prev split=false
 -
 -    # Get cur and prev words; but don't treat user:group as separate words.
 -    _get_comp_words_by_ref -n : cur prev
 -
 -    _split_longopt && split=true
 -
 -    case "$prev" in
 -        --from)
 -            _usergroup
 -            return 0
 -            ;;
 -        --reference)
 -            _filedir
 -            return 0
 -            ;;
 -    esac
 -
 -    $split && return 0
 -
 -    if [[ "$cur" == -* ]]; then
 -        # Complete -options
 -        COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes --dereference \
 -            --no-dereference --from --silent --quiet --reference --recursive \
 -            --verbose --help --version' -- "$cur" ) )
 -    else
 -        local args
 -
 -        # The first argument is an usergroup; the rest are filedir.
 -        _count_args :
 -
 -        if [[ $args == 1 ]]; then
 -            _usergroup
 -        else
 -            _filedir
 -        fi
 -    fi
 -} # _chown()
 -complete -F _chown -o filenames chown
 -
 -
 -# chgrp(1) completion
 -#
 -_chgrp()
 -{
 -    local cur prev split=false
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur prev
 -    cur=${cur//\\\\/}
 -
 -    _split_longopt && split=true
 -
 -    if [[ "$prev" == --reference ]]; then
 -        _filedir
 -        return 0
 -    fi
 -
 -    $split && return 0
 -
 -    # options completion
 -    if [[ "$cur" == -* ]]; then
 -        COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes --dereference \
 -            --no-dereference --silent --quiet --reference --recursive \
 -            --verbose --help --version' -- "$cur" ) )
 -        return 0
 -    fi
 -
 -    # first parameter on line or first since an option?
 -    if [[ $COMP_CWORD -eq 1 && "$cur" != -* || "$prev" == -* ]]; then
 -        local IFS=$'\n'
 -        COMPREPLY=( $( compgen -g "$cur" 2>/dev/null ) )
 -    else
 -        _filedir || return 0
 -    fi
 -
 -    return 0
 -} # _chgrp()
 -complete -F _chgrp -o filenames chgrp
 -
 -
 -# Linux rmmod(8) completion. This completes on a list of all currently
 -# installed kernel modules.
 -#
 -have rmmod && {
 -_rmmod()
 -{
 -    local cur
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur
 -
 -    _installed_modules "$cur"
 -    return 0
 -} # _rmmod()
 -complete -F _rmmod rmmod
 -
 -
 -# Linux insmod(8), modprobe(8) and modinfo(8) completion. This completes on a
 -# list of all available modules for the version of the kernel currently
 -# running.
 -#
 -_insmod()
 -{
 -    local cur prev modpath
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur prev
 -
 -    # behave like lsmod for modprobe -r
 -    if [[ ${1##*/} == modprobe && "${COMP_WORDS[1]}" == -r ]]; then
 -        _installed_modules "$cur"
 -        return 0
 -    fi
 -
 -    # do filename completion if we're giving a path to a module
 -    if [[ "$cur" == */* ]]; then
 -        _filedir '@(?(k)o?(.gz))'
 -        return 0
 -    fi
 -
 -    if [[ $COMP_CWORD -gt 1 && "${COMP_WORDS[COMP_CWORD-1]}" != -* ]]; then
 -        # do module parameter completion
 -        COMPREPLY=( $( compgen -W "$( /sbin/modinfo -p ${COMP_WORDS[1]} | \
 -            cut -d: -f1 )" -- "$cur" ) )
 -    else
 -        _modules $(uname -r)
 -    fi
 -
 -    return 0
 -} # _insmod
 -complete -F _insmod -o filenames insmod modprobe modinfo
 -} # have rmmod
 -
 -
 -# renice(8) completion
 -#
 -_renice()
 -{
 -    local command cur curopt i
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur
 -    command=$1
 -
 -    i=0
 -    # walk back through command line and find last option
 -    while [[ $i -le $COMP_CWORD && ${#COMPREPLY[@]} -eq 0 ]]; do
 -        curopt=${COMP_WORDS[COMP_CWORD-$i]}
 -        case "$curopt" in
 -            -u)
 -                COMPREPLY=( $( compgen -u -- "$cur" ) )
 -                ;;
 -            -g)
 -                _pgids
 -                ;;
 -            -p|$command)
 -                _pids
 -                ;;
 -        esac
 -        i=$(( ++i ))
 -    done
 -}
 -complete -F _renice renice
 -
 -
 -# kill(1) completion
 -#
 -_kill()
 -{
 -    local cur
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur
 -
 -    if [[ $COMP_CWORD -eq 1 && "$cur" == -* ]]; then
 -        # return list of available signals
 -        _signals
 -    else
 -        # return list of available PIDs
 -        _pids
 -    fi
 -}
 -complete -F _kill kill
 -
 -# killall(1) (Linux and FreeBSD) and pkill(1) completion.
 -#
 -[[ $UNAME == Linux || $UNAME == FreeBSD ]] || have pkill &&
 -_killall()
 -{
 -    local cur
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur
 -
 -    if [[ $COMP_CWORD -eq 1 && "$cur" == -* ]]; then
 -        _signals
 -    else
 -        _pnames
 -    fi
 -
 -    return 0
 -}
 -[[ $UNAME == Linux || $UNAME == FreeBSD ]] && complete -F _killall killall
 -have pkill && complete -F _killall pkill
 -
 -# pgrep(1) completion.
 -#
 -[ $UNAME = Linux ] || have pgrep &&
 -_pgrep()
 -{
 -    local cur
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur
 -
 -    _pnames
 -
 -    return 0
 -}
 -have pgrep && complete -F _pgrep pgrep
 -
 -# Linux pidof(8) completion.
 -[ $UNAME = Linux ] && complete -F _pgrep pidof
 -
 -# Red Hat & Debian GNU/Linux if{up,down} completion
 -#
 -[ $USERLAND = GNU ] && { have ifup || have ifdown; } &&
 -_ifupdown()
 -{
 -    local cur
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur
 -
 -    if [ $COMP_CWORD -eq 1 ]; then
 -        _configured_interfaces
 -        COMPREPLY=( $(compgen -W '${COMPREPLY[@]}' -- "$cur") )
 -    fi
 -
 -    return 0
 -} &&
 -complete -F _ifupdown ifup ifdown
 -[ $USERLAND = GNU ] && have ifstatus && complete -F _ifupdown ifstatus
 -
 -# Linux ipsec(8) completion (for FreeS/WAN)
 -#
 -[ $UNAME = Linux ] && have ipsec &&
 -_ipsec()
 -{
 -    local cur
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur
 -
 -    if [ $COMP_CWORD -eq 1 ]; then
 -        COMPREPLY=( $( compgen -W 'auto barf eroute klipsdebug look manual \
 -            pluto ranbits rsasigkey setup showdefaults showhostkey spi spigrp \
 -            tncfg whack' -- "$cur" ) )
 -        return 0
 -    fi
 -
 -    case ${COMP_WORDS[1]} in
 -        auto)
 -            COMPREPLY=( $( compgen -W '--asynchronous --up --add --delete \
 -                --replace --down --route --unroute \
 -                --ready --status --rereadsecrets' \
 -                -- "$cur" ) )
 -            ;;
 -        manual)
 -            COMPREPLY=( $( compgen -W '--up --down --route --unroute \
 -                --union' -- "$cur" ) )
 -            ;;
 -        ranbits)
 -            COMPREPLY=( $( compgen -W '--quick --continuous --bytes' \
 -                -- "$cur" ) )
 -            ;;
 -        setup)
 -            COMPREPLY=( $( compgen -W '--start --stop --restart' -- "$cur" ) )
 -            ;;
 -        *)
 -            ;;
 -    esac
 -
 -    return 0
 -} &&
 -complete -F _ipsec ipsec
 -
  # This function provides simple user at host completion
  #
  _user_at_host() {
      local cur
  
      COMPREPLY=()
-     cur=`_get_cword :`
+     _get_comp_words_by_ref -n : cur
  
      if [[ $cur == *@* ]]; then
          _known_hosts_real "$cur"
@@@ -1294,7 -1608,8 +1342,8 @@@ complete -F _known_hosts traceroute tra
  #
  _cd()
  {
-     local IFS=$'\t\n' cur=`_get_cword` i j k
+     local cur IFS=$'\t\n' i j k
+     _get_comp_words_by_ref cur
  
      # try to allow variable completion
      if [[ "$cur" == ?(\\)\$* ]]; then
@@@ -1397,7 -1712,7 +1446,7 @@@ _command_offset(
      COMP_CWORD=$(( $COMP_CWORD - $word_offset ))
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      if [[ $COMP_CWORD -eq 0 ]]; then
          COMPREPLY=( $( compgen -c -- "$cur" ) )
@@@ -1439,12 -1754,11 +1488,12 @@@
      [ ${#COMPREPLY[@]} -eq 0 ] && _filedir
  }
  complete -F _command -o filenames nohup exec nice eval time ltrace then \
 -    else do vsound command xargs tsocks
 +    else do vsound command xargs tsocks aoss padsp
  
  _root_command()
  {
 -    PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin _command $1 $2 $3
 +    local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
 +    _command $1 $2 $3
  }
  complete -F _root_command -o filenames sudo fakeroot really gksudo gksu kdesudo
  
@@@ -1452,8 -1766,7 +1501,7 @@@ _longopt(
  {
      local cur prev
  
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      if _split_longopt; then
          case "$prev" in
@@@ -1483,29 -1796,64 +1531,29 @@@ for i in a2ps autoconf automake bc gpro
      touch vdir awk gperf grep grub indent less m4 sed shar date \
      tee who texindex cat csplit cut expand fmt fold head \
      md5sum nl od paste pr ptx sha1sum sort split tac tail tr unexpand \
 -    uniq wc ldd bash id irb mkdir rmdir; do
 +    uniq wc ldd bash id irb mkdir rmdir wget curl; do
      have $i && complete -F _longopt -o filenames $i
  done
  
  # These commands do not use filenames, so '-o filenames' is not needed.
 -for i in env netstat seq uname units wget; do
 +for i in env netstat seq uname units; do
      have $i && complete -F _longopt -o default $i
  done
  unset i
  
 -# look(1) completion
 -#
 -have look &&
 -_look()
 -{
 -    local cur
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur
 -
 -    if [ $COMP_CWORD = 1 ]; then
 -        COMPREPLY=( $( compgen -W '$(look "$cur" 2>/dev/null)' -- "$cur" ) )
 -    fi
 -} &&
 -complete -F _look -o default look
 -
 -# id(1) completion
 -#
 -have id &&
 -_id()
 -{
 -    local cur
 -
 -    COMPREPLY=()
 -    _get_comp_words_by_ref cur
 -
 -    if [[ "$cur" == -* ]]; then
 -        COMPREPLY=( $( compgen -W '-a -g --group -G --groups -n --name\
 -            -r --real -u --user --help --version' -- "$cur" ) )
 -    else
 -        COMPREPLY=( $( compgen -u "$cur" ) )
 -    fi
 -} &&
 -complete -F _id id
 -
  _filedir_xspec()
  {
      local IFS cur xspec
  
      IFS=$'\t\n'
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      _expand || return 0
  
      # get first exclusion compspec that matches this command
      xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \$0; exit }" \
 -        $BASH_COMPLETION )
 +        "$BASH_COMPLETION" )
      # prune to leave nothing but the -X spec
      xspec=${xspec#*-X }
      xspec=${xspec%% *}
@@@ -1532,7 -1880,7 +1580,7 @@@
  
      COMPREPLY=( "${toks[@]}" )
  }
 -list=( $( sed -ne '/^# START exclude/,/^# FINISH exclude/p' $BASH_COMPLETION | \
 +list=( $( sed -ne '/^# START exclude/,/^# FINISH exclude/p' "$BASH_COMPLETION" | \
      # read exclusion compspecs
      (
      while read line
@@@ -1558,19 -1906,19 +1606,19 @@@ unset lis
  # source completion directory definitions
  if [[ -d $BASH_COMPLETION_COMPAT_DIR && -r $BASH_COMPLETION_COMPAT_DIR && \
      -x $BASH_COMPLETION_COMPAT_DIR ]]; then
 -    for i in $(LC_ALL=C command ls $BASH_COMPLETION_COMPAT_DIR); do
 +    for i in $(LC_ALL=C command ls "$BASH_COMPLETION_COMPAT_DIR"); do
          i=$BASH_COMPLETION_COMPAT_DIR/$i
          [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) \
 -            && ( -f $i || -h $i ) && -r $i ]] && . $i
 +            && ( -f $i || -h $i ) && -r $i ]] && . "$i"
      done
  fi
  if [[ $BASH_COMPLETION_DIR != $BASH_COMPLETION_COMPAT_DIR && \
      -d $BASH_COMPLETION_DIR && -r $BASH_COMPLETION_DIR && \
      -x $BASH_COMPLETION_DIR ]]; then
 -    for i in $(LC_ALL=C command ls $BASH_COMPLETION_DIR); do
 +    for i in $(LC_ALL=C command ls "$BASH_COMPLETION_DIR"); do
          i=$BASH_COMPLETION_DIR/$i
          [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) \
 -            && ( -f $i || -h $i ) && -r $i ]] && . $i
 +            && ( -f $i || -h $i ) && -r $i ]] && . "$i"
      done
  fi
  unset i
diff --combined contrib/_mock
index 76ecb8a,0000000..f16f116
mode 100644,000000..100644
--- a/contrib/_mock
+++ b/contrib/_mock
@@@ -1,87 -1,0 +1,86 @@@
 +# Use of this file is deprecated.  Upstream completion is available in
 +# mock > 1.1.0, use that instead.
 +
 +# bash completion for mock
 +
 +have mock &&
 +_mock()
 +{
 +    local cur prev plugins cfgdir split=false
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
++    _get_comp_words_by_ref cur prev
 +    plugins='tmpfs root_cache yum_cache bind_mount ccache'
 +    cfgdir=/etc/mock
 +
 +    count=0
 +    for i in "${COMP_WORDS[@]}" ; do
 +        [ $count -eq $COMP_CWORD ] && break
 +        if [[ "$i" == --configdir ]] ; then
 +            cfgdir="${COMP_WORDS[((count+1))]}"
 +        elif [[ "$i" == --configdir=* ]] ; then
 +            cfgdir=${i/*=/}
 +        fi
 +        count=$((++count))
 +    done
 +
 +    _split_longopt && split=true
 +
 +    case $prev in
 +        -h|--help|--copyin|--copyout|--arch|-D|--define|--with|--without|--uniqueext|--rpmbuild_timeout|--sources|--cwd)
 +            return 0
 +            ;;
 +        -r|--root)
 +            COMPREPLY=( $( compgen -W "$( command ls $cfgdir )" -- $cur ) )
 +            COMPREPLY=( ${COMPREPLY[@]/%.cfg/} )
 +            return 0
 +            ;;
 +        --configdir|--resultdir)
 +            _filedir -d
 +            return 0
 +            ;;
 +        --spec)
 +            _filedir spec
 +            return 0
 +            ;;
 +        --target)
 +            # Yep, compatible archs, not compatible build archs
 +            # (e.g. ix86 chroot builds in x86_64 mock host)
 +            # This would actually depend on what the target root
 +            # can be used to build for...
 +            COMPREPLY=( $( compgen -W "$( command rpm --showrc | \
 +                sed -ne 's/^\s*compatible\s\s*archs\s*:\s*\(.*\)/\1/i p' )" \
 +                -- "$cur" ) )
 +            return 0
 +            ;;
 +        --enable-plugin|--disable-plugin)
 +            COMPREPLY=( $( compgen -W "$plugins" -- "$cur" ) )
 +            return 0
 +            ;;
 +    esac
 +
 +    $split && return 0
 +
 +    if [[ "$cur" == -* ]] ; then
 +        COMPREPLY=( $( compgen -W '--version --help --rebuild \
 +            --buildsrpm --shell --chroot --clean --init \
 +            --installdeps --install --update --orphanskill \
 +            --copyin --copyout --root --offline --no-clean \
 +            --cleanup-after --no-cleanup-after --arch --target \
 +            --define --with --without --resultdir --uniqueext \
 +            --configdir --rpmbuild_timeout --unpriv --cwd --spec \
 +            --sources --verbose --quiet --trace --enable-plugin \
 +            --disable-plugin --print-root-path' -- "$cur" ) )
 +    else
 +        _filedir '?(no)src.rpm'
 +    fi
 +} &&
 +complete -F _mock -o filenames mock
 +
 +# Local variables:
 +# mode: shell-script
 +# sh-basic-offset: 4
 +# sh-indent-comment: t
 +# indent-tabs-mode: nil
 +# End:
 +# ex: ts=4 sw=4 et filetype=sh
diff --combined contrib/apache2ctl
index 1d6ff83,5214ba3..287443a
--- a/contrib/apache2ctl
+++ b/contrib/apache2ctl
@@@ -2,10 -2,10 +2,10 @@@
  
  have apache2ctl && {
  _apache2ctl() {
 -    local APWORDS
 +    local APWORDS cur
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      APWORDS=$(apache2ctl 2>&1 >/dev/null | awk 'NR<2 { print $3; exit }' | \
          tr "|" " ")
diff --combined contrib/bluez
index a420398,4b5f8f9..7a2b1e5
--- a/contrib/bluez
+++ b/contrib/bluez
@@@ -28,13 -28,25 +28,12 @@@ _bluetooth_packet_types(
          -- "$cur" ) )
  }
  
 -_get_command()
 -{
 -    local i
 -
 -    command=
 -    for (( i=1; i < COMP_CWORD; i++ )); do
 -        if [[ "${COMP_WORDS[i]}" != -* ]]; then
 -            command=${COMP_WORDS[i]}
 -            break
 -        fi
 -    done
 -}
 -
  _hcitool()
  {
 -    local cur prev split=false
 +    local cur prev split=false arg
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      _split_longopt && split=true
  
@@@ -55,8 -67,8 +54,8 @@@
  
      $split && return 0
  
 -    _get_command
 -    if [ -z $command ]; then
 +    _get_first_arg
 +    if [ -z $arg ]; then
          if [[ "$cur" == -* ]]; then
              COMPREPLY=( $( compgen -W '--help -i' -- "$cur" ) )
          else
@@@ -65,7 -77,7 +64,7 @@@
                  afh lst auth enc key clkoff clock' -- "$cur" ) )
          fi
      else
 -        case $command in
 +        case $arg in
              name|info|dc|rssi|lq|afh|auth|key|clkoff|lst)
                  _count_args
                  if [ $args -eq 2 ]; then
@@@ -116,8 -128,7 +115,7 @@@ _sdptool(
      local cur prev split=false
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      _split_longopt && split=true
  
@@@ -130,8 -141,8 +128,8 @@@
  
      $split && return 0
  
 -    _get_command
 -    if [ -z $command ]; then
 +    _get_first_arg
 +    if [ -z $arg ]; then
          if [[ "$cur" == -* ]]; then
              COMPREPLY=( $( compgen -W '--help' -- "$cur" ) )
          else
@@@ -139,7 -150,7 +137,7 @@@
                  del get setattr setseq' -- "$cur" ) )
          fi
      else
 -        case $command in
 +        case $arg in
              search)
                  if [[ "$cur" == -* ]]; then
                      COMPREPLY=( $( compgen -W '--bdaddr \
@@@ -178,8 -189,7 +176,7 @@@ _l2ping(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
@@@ -202,8 -212,7 +199,7 @@@ _rfcomm(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -f|--config)
@@@ -217,8 -226,8 +213,8 @@@
              ;;
      esac
  
 -    _get_command
 -    if [ -z $command ]; then
 +    _get_first_arg
 +    if [ -z $arg ]; then
          if [[ "$cur" == -* ]]; then
              COMPREPLY=( $( compgen -W '--help -a --raw \
                  --config -i --auth --encrypt --secure --master' -- "$cur" ) )
@@@ -231,7 -240,7 +227,7 @@@
          if [ $args -eq 2 ]; then
              _bluetooth_devices
          else
 -            case $command in
 +            case $arg in
                  connect|bind)
                      if [ $args -eq 3 ]; then
                          _bluetooth_adresses
@@@ -248,8 -257,7 +244,7 @@@ _ciptool(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
@@@ -259,8 -267,8 +254,8 @@@
              ;;
      esac
  
 -    _get_command
 -    if [ -z $command ]; then
 +    _get_first_arg
 +    if [ -z $arg ]; then
          if [[ "$cur" == -* ]]; then
              COMPREPLY=( $( compgen -W '--help -i' -- "$cur" ) )
          else
@@@ -268,7 -276,7 +263,7 @@@
                  loopback' -- "$cur" ) )
          fi
      else
 -        case $command in
 +        case $arg in
              connect|release|loopback)
                  _count_args
                  if [ $args -eq 2 ]; then
@@@ -285,8 -293,7 +280,7 @@@ _dfutool(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -d|--device)
@@@ -317,10 -324,10 +311,10 @@@ _hciconfig(
      local cur
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
 -    _get_command
 -    if [ -z $command ]; then
 +    _get_first_arg
 +    if [ -z $arg ]; then
          if [[ "$cur" == -* ]]; then
              COMPREPLY=( $( compgen -W '--help --all' -- "$cur" ) )
          else
@@@ -333,7 -340,7 +327,7 @@@
                  -- "$cur" ) )
          fi
      else
 -        case $command in
 +        case $arg in
              putkey|delkey)
                  _count_args
                  if [ $args -eq 2 ]; then
@@@ -363,7 -370,7 +357,7 @@@ _hciattach(
      local cur
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W '-n -p -t -b -s -l' -- "$cur" ) )
@@@ -401,7 -408,7 +395,7 @@@ _hid2hci(
      local cur
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W '--help --quiet -0 --tohci -1 \
@@@ -415,7 -422,7 +409,7 @@@ _avctrl(
      local cur
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W '--help --quiet' -- "$cur" ) )
diff --combined contrib/cfengine
index 63df340,8a85005..50a1384
--- a/contrib/cfengine
+++ b/contrib/cfengine
@@@ -3,13 -3,16 +3,13 @@@
  have cfagent && {
  _cfagent_options()
  {
 -    COMPREPLY=( $( compgen -W '-a --sysadm -b --force-net-copy -c \
 -        --no-check-files -C --no-check-mounts -d --debug -D --define \
 -        -e --no-edits -E --enforce-links -f --file -h --help -H \
 -        --no-hard-classes -i --no-ifconfig -I --inform -k --no-copy \
 -        -K --no-lock -l --traverse-links -L --delete-stale-links -m \
 -        --no-mount -M --no-modules -n --recon --dry-run --just-print \
 -        -N --negate --undefine -p --parse-only -P --no-processes -q \
 -        --no-splay -s --no-commands -S --silent -t --no-tidy -u \
 -        --use-env -U --underscore-classes -v --verbose -V --version \
 -        -x --no-preconf -X --no-links -w --no-warn --quiet' -- "$cur" ) )
 +    COMPREPLY=( $( compgen -W '--sysadm --force-net-copy --no-check-files \
 +        --no-check-mounts --debug --define --no-edits --enforce-links --file \
 +        --help --no-hard-classes --no-ifconfig --inform --no-copy --no-lock \
 +        --traverse-links --delete-stale-links --no-mount --no-modules \
 +        --dry-run --negate --parse-only --no-processes --no-splay \
 +        --no-commands --silent --no-tidy --use-env --underscore-classes \
 +        --verbose --version --no-preconf --no-links --quiet' -- "$cur" ) )
  }
  
  _cfagent()
@@@ -17,8 -20,7 +17,7 @@@
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -f|--file)
@@@ -35,10 -37,10 +34,10 @@@ complete -F _cfagent cfagen
  
  _cfrun()
  {
-     local i section cfinputs
+     local i section cfinputs cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur prev
  
      section=1
      for (( i=1; i < COMP_CWORD; i++ )); do
@@@ -49,7 -51,6 +48,6 @@@
  
      case $section in
          1)
-             prev=${COMP_WORDS[COMP_CWORD-1]}
              case $prev in
                  -f)
                      _filedir
diff --combined contrib/coreutils
index 8146e9a,0000000..65809fb
mode 100644,000000..100644
--- a/contrib/coreutils
+++ b/contrib/coreutils
@@@ -1,124 -1,0 +1,122 @@@
 +# Completions for various core utilities
 +
 +# chown(1) completion
 +#
 +have chown &&
 +_chown()
 +{
 +    local cur prev split=false
 +
 +    # Get cur and prev words; but don't treat user:group as separate words.
-     cur=`_get_cword :`
-     prev=`_get_pword :`
++    _get_comp_words_by_ref -n : cur prev
 +
 +    _split_longopt && split=true
 +
 +    case "$prev" in
 +        --from)
 +            _usergroup
 +            return 0
 +            ;;
 +        --reference)
 +            _filedir
 +            return 0
 +            ;;
 +    esac
 +
 +    $split && return 0
 +
 +    if [[ "$cur" == -* ]]; then
 +        # Complete -options
 +        local w opts
 +        for w in "${COMP_WORDS[@]}" ; do
 +            [[ "$w" == -@(R|-recursive) ]] && opts="-H -L -P" && break
 +        done
 +        COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes --dereference \
 +            --no-dereference --from --silent --quiet --reference --recursive \
 +            --verbose --help --version $opts' -- "$cur" ) )
 +    else
 +        local args
 +
 +        # The first argument is an usergroup; the rest are filedir.
 +        _count_args :
 +
 +        if [[ $args == 1 ]]; then
 +            _usergroup
 +        else
 +            _filedir
 +        fi
 +    fi
 +} &&
 +complete -F _chown -o filenames chown
 +
 +
 +# chgrp(1) completion
 +#
 +have chgrp &&
 +_chgrp()
 +{
 +    local cur prev split=false
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur prev
 +    cur=${cur//\\\\/}
-     prev=${COMP_WORDS[COMP_CWORD-1]}
 +
 +    _split_longopt && split=true
 +
 +    if [[ "$prev" == --reference ]]; then
 +        _filedir
 +        return 0
 +    fi
 +
 +    $split && return 0
 +
 +    # options completion
 +    if [[ "$cur" == -* ]]; then
 +        local w opts
 +        for w in "${COMP_WORDS[@]}" ; do
 +            [[ "$w" == -@(R|-recursive) ]] && opts="-H -L -P" && break
 +        done
 +        COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes --dereference \
 +            --no-dereference --silent --quiet --reference --recursive \
 +            --verbose --help --version $opts' -- "$cur" ) )
 +        return 0
 +    fi
 +
 +    # first parameter on line or first since an option?
 +    if [[ $COMP_CWORD -eq 1 && "$cur" != -* || "$prev" == -* ]]; then
 +        local IFS=$'\n'
 +        COMPREPLY=( $( compgen -g "$cur" 2>/dev/null ) )
 +    else
 +        _filedir || return 0
 +    fi
 +
 +    return 0
 +} &&
 +complete -F _chgrp -o filenames chgrp
 +
 +# id(1) completion
 +#
 +have id &&
 +_id()
 +{
 +    local cur
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur
 +
 +    if [[ "$cur" == -* ]]; then
 +        COMPREPLY=( $( compgen -W '-a -g --group -G --groups -n --name\
 +            -r --real -u --user --help --version' -- "$cur" ) )
 +    else
 +        COMPREPLY=( $( compgen -u "$cur" ) )
 +    fi
 +} &&
 +complete -F _id id
 +
 +# Local variables:
 +# mode: shell-script
 +# sh-basic-offset: 4
 +# sh-indent-comment: t
 +# indent-tabs-mode: nil
 +# End:
 +# ex: ts=4 sw=4 et filetype=sh
diff --combined contrib/dsniff
index 95875be,ab93343..1d3b303
--- a/contrib/dsniff
+++ b/contrib/dsniff
@@@ -6,12 -6,11 +6,11 @@@ _arpspoof(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=`_get_pword`
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
 -            _interfaces
 +            _available_interfaces
              return 0
              ;;
          -t)
@@@ -35,8 -34,7 +34,7 @@@ _dnsspoof(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
@@@ -62,8 -60,7 +60,7 @@@ _dsniff(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -r|-w|-f)
@@@ -89,8 -86,7 +86,7 @@@ _snarf(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
@@@ -112,8 -108,7 +108,7 @@@ _macof(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
@@@ -136,7 -131,7 +131,7 @@@ _sshmitm(
      local cur
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W '-d -I -p' -- "$cur" ) )
@@@ -153,8 -148,7 +148,7 @@@ _sshow(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
@@@ -176,8 -170,7 +170,7 @@@ _tcpkill(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
@@@ -199,8 -192,7 +192,7 @@@ _tcpnice(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
@@@ -222,8 -214,7 +214,7 @@@ _urlsnarf(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
@@@ -245,7 -236,7 +236,7 @@@ _webmitm(
      local cur
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W '-d' -- "$cur" ) )
diff --combined contrib/findutils
index 73179a4,551839e..6af5d50
--- a/contrib/findutils
+++ b/contrib/findutils
@@@ -8,67 -8,61 +8,66 @@@ _find(
      local cur prev i exprfound onlyonce
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
 -    -maxdepth|-mindepth)
 -        COMPREPLY=( $( compgen -W '0 1 2 3 4 5 6 7 8 9' -- "$cur" ) )
 -        return 0
 -        ;;
 -    -newer|-anewer|-cnewer|-fls|-fprint|-fprint0|-fprintf|-name|-iname| \
 -    -lname|-ilname|-wholename|-iwholename)
 -        _filedir
 -        return 0
 -        ;;
 -    -fstype)
 -        # this is highly non-portable
 -        [ -e /proc/filesystems ] &&
 -            COMPREPLY=( $( compgen -W "$( cut -d$'\t' -f2 /proc/filesystems )" \
 -            -- "$cur" ) )
 -        return 0
 -        ;;
 -    -gid)
 -        _gids
 -        return 0
 -        ;;
 -    -group)
 -        COMPREPLY=( $( compgen -g -- "$cur" 2>/dev/null) )
 -        return 0
 -        ;;
 -    -xtype|-type)
 -        COMPREPLY=( $( compgen -W 'b c d p f l s' -- "$cur" ) )
 -        return 0
 -        ;;
 -    -uid)
 -        _uids
 -        return 0
 -        ;;
 -    -user)
 -        COMPREPLY=( $( compgen -u -- "$cur" ) )
 -        return 0
 -        ;;
 -    -exec|-ok)
 -        COMP_WORDS=(COMP_WORDS[0] "$cur")
 -        COMP_CWORD=1
 -        _command
 -        return 0
 -        ;;
 -    -[acm]min|-[acm]time|-iname|-lname|-wholename|-iwholename|-lwholename| \
 -    -ilwholename|-inum|-path|-ipath|-regex|-iregex|-links|-perm|-size| \
 -    -used|-printf)
 -        # do nothing, just wait for a parameter to be given
 -        return 0
 -        ;;
 +        -maxdepth|-mindepth)
 +            COMPREPLY=( $( compgen -W '0 1 2 3 4 5 6 7 8 9' -- "$cur" ) )
 +            return 0
 +            ;;
 +        -newer|-anewer|-cnewer|-fls|-fprint|-fprint0|-fprintf|-name|-iname|\
 +        -lname|-ilname|-wholename|-iwholename|-samefile)
 +            _filedir
 +            return 0
 +            ;;
 +        -fstype)
 +            _fstypes
 +            if [[ "$( uname -s )" == *BSD ]] ; then
 +                COMPREPLY=( "${COMPREPLY[@]}" \
 +                    $( compgen -W 'local rdonly' -- "$cur" ) )
 +            fi
 +            return 0
 +            ;;
 +        -gid)
 +            _gids
 +            return 0
 +            ;;
 +        -group)
 +            COMPREPLY=( $( compgen -g -- "$cur" 2>/dev/null) )
 +            return 0
 +            ;;
 +        -xtype|-type)
 +            COMPREPLY=( $( compgen -W 'b c d p f l s' -- "$cur" ) )
 +            return 0
 +            ;;
 +        -uid)
 +            _uids
 +            return 0
 +            ;;
 +        -user)
 +            COMPREPLY=( $( compgen -u -- "$cur" ) )
 +            return 0
 +            ;;
 +        -exec|-execdir|-ok|-okdir)
 +            COMP_WORDS=(COMP_WORDS[0] "$cur")
 +            COMP_CWORD=1
 +            _command
 +            return 0
 +            ;;
 +        -[acm]min|-[acm]time|-iname|-lname|-wholename|-iwholename|-lwholename|\
 +        -ilwholename|-inum|-path|-ipath|-regex|-iregex|-links|-perm|-size|\
 +        -used|-printf|-context)
 +            # do nothing, just wait for a parameter to be given
 +            return 0
 +            ;;
 +        -regextype)
 +            COMPREPLY=( $( compgen -W 'emacs posix-awk posix-basic \
 +                posix-egrep posix-extended' -- "$cur" ) )
 +            return 0
 +            ;;
      esac
  
      _expand || return 0
 -
      # set exprfound to 1 if there is already an expression present
      for i in ${COMP_WORDS[@]}; do
          [[ "$i" = [-\(\),\!]* ]] && exprfound=1 && break
@@@ -81,25 -75,22 +80,25 @@@
      fi
  
      # complete using basic options
 -    COMPREPLY=( $( compgen -W '-daystart -depth -follow -help -maxdepth \
 -        -mindepth -mount -noleaf -version -xdev -amin -anewer \
 -        -atime -cmin -cnewer -ctime -empty -false -fstype \
 -        -gid -group -ilname -iname -inum -ipath -iregex \
 -        -wholename \
 -        -links -lname -mmin -mtime -name -newer -nouser \
 -        -nogroup -perm -regex -size -true -type -uid -used \
 -        -user -xtype -exec -fls -fprint -fprint0 -fprintf -ok \
 -        -print -print0 -printf -prune -ls -wholename -iwholename' -- "$cur" ) )
 +    COMPREPLY=( $( compgen -W '-daystart -depth -follow -help \
 +        -ignore_readdir_race -maxdepth -mindepth -mindepth -mount \
 +        -noignore_readdir_race -noleaf -regextype -version -warn -nowarn \
 +        -xdev \
 +        -amin -anewer -atime -cmin -cnewer -ctime -empty -executable -false \
 +        -fstype -gid -group -ilname -iname -inum -ipath -iregex -iwholename \
 +        -links -lname -mmin -mtime -name -newer -nogroup -nouser -path -perm \
 +        -readable -regex -samefile -size -true -type -uid -used -user \
 +        -wholename -writable -xtype -context \
 +        -delete -exec -execdir -fls -fprint -fprint0 -fprintf -ls -ok -okdir \
 +        -print -print0 -printf -prune -quit' -- "$cur" ) )
  
      # this removes any options from the list of completions that have
      # already been specified somewhere on the command line, as long as
      # these options can only be used once (in a word, "options", in
      # opposition to "tests" and "actions", as in the find(1) manpage).
 -    onlyonce=' -daystart -depth -follow -help -maxdepth -mindepth -mount \
 -       -noleaf -version -xdev '
 +    onlyonce=' -daystart -depth -follow -help -ignore_readdir_race -maxdepth \
 +       -mindepth -mount -noignore_readdir_race -noleaf -nowarn -regextype \
 +       -version -warn -xdev '
      COMPREPLY=( $( \
             (while read -d ' ' i; do
              [[ -z "$i" || "${onlyonce/ ${i%% *} / }" == "$onlyonce" ]] &&
diff --combined contrib/gzip
index 931423d,50f59fb..0951f72
--- a/contrib/gzip
+++ b/contrib/gzip
@@@ -6,8 -6,7 +6,7 @@@ _gzip(
      local cur prev xspec helpopts
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
      helpopts=`_parse_help ${COMP_WORDS[0]}`
  
      case $prev in
@@@ -24,7 -23,7 +23,7 @@@
  
      local IFS=$'\t\n'
  
 -    xspec="*.?(t)gz"
 +    xspec="*.@(gz|t[ag]z)"
      if [[ "$prev" == --* ]]; then
          [[ "$prev" == --decompress || \
              "$prev" == --list || \
diff --combined contrib/iconv
index 959ce40,583f2a6..14b618d
--- a/contrib/iconv
+++ b/contrib/iconv
@@@ -3,42 -3,27 +3,41 @@@
  have iconv &&
  _iconv()
  {
 -    local cur prev
 +    local cur prev split=false
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
 +    _split_longopt && split=true
 +
      case $prev in
 -        -f|-t|--from-code|--to-code)
 -            COMPREPLY=( $( compgen -W \
 -                '$( iconv --list | sed -e "s@//@@;" )' -- "$cur" ) )
 +        -'?'|--help|--usage|-V|--version|--unicode-subst|--byte-subst|\
 +        --widechar-subst)
 +            return 0
 +            ;;
 +        -f|--from-code|-t|--to-code)
 +            COMPREPLY=( $( compgen -W '$( iconv -l | \
 +                sed -e "s@/*\$@@" -e "s/[,()]//g" )' -- "$cur" ) )
 +            return 0
 +            ;;
 +        -o|--output)
 +            _filedir
              return 0
              ;;
      esac
  
 +    $split && return 0
  
      if [[ "$cur" = -* ]]; then
 -        COMPREPLY=( $( compgen -W '--from-code -f --to-code -t --list
 -            --output -o --verbose' -- "$cur" ) )
 +        COMPREPLY=( $( compgen -W '--from-code --to-code --list -c
 +            --unicode-subst --byte-subst --widechar-subst --output --silent
 +            --verbose --help --usage --version' -- "$cur" ) )
          return 0
      fi
  } &&
  complete -F _iconv -o default iconv
 +# Intentionally not -o filenames here, -f/-t completions may contain slashes
 +# and -o filenames would break them.
  
  # Local variables:
  # mode: shell-script
diff --combined contrib/ifupdown
index 4157179,0000000..f81e08d
mode 100644,000000..100644
--- a/contrib/ifupdown
+++ b/contrib/ifupdown
@@@ -1,27 -1,0 +1,27 @@@
 +# Red Hat & Debian GNU/Linux if{up,down} completion
 +#
 +[ $USERLAND = GNU ] && { have ifup || have ifdown; } &&
 +_ifupdown()
 +{
 +    local cur
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur
 +
 +    if [ $COMP_CWORD -eq 1 ]; then
 +        _configured_interfaces
 +        COMPREPLY=( $(compgen -W '${COMPREPLY[@]}' -- "$cur") )
 +    fi
 +
 +    return 0
 +} &&
 +complete -F _ifupdown ifup ifdown
 +[ $USERLAND = GNU ] && have ifstatus && complete -F _ifupdown ifstatus
 +
 +# Local variables:
 +# mode: shell-script
 +# sh-basic-offset: 4
 +# sh-indent-comment: t
 +# indent-tabs-mode: nil
 +# End:
 +# ex: ts=4 sw=4 et filetype=sh
diff --combined contrib/ipsec
index 86da498,0000000..acb8c99
mode 100644,000000..100644
--- a/contrib/ipsec
+++ b/contrib/ipsec
@@@ -1,51 -1,0 +1,51 @@@
 +# Linux ipsec(8) completion (for FreeS/WAN)
 +#
 +[ $UNAME = Linux ] && have ipsec &&
 +_ipsec()
 +{
 +    local cur
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur
 +
 +
 +    if [ $COMP_CWORD -eq 1 ]; then
 +        COMPREPLY=( $( compgen -W 'auto barf eroute klipsdebug look manual \
 +            pluto ranbits rsasigkey setup showdefaults showhostkey spi spigrp \
 +            tncfg whack' -- "$cur" ) )
 +        return 0
 +    fi
 +
 +    case ${COMP_WORDS[1]} in
 +        auto)
 +            COMPREPLY=( $( compgen -W '--asynchronous --up --add --delete \
 +                --replace --down --route --unroute \
 +                --ready --status --rereadsecrets' \
 +                -- "$cur" ) )
 +            ;;
 +        manual)
 +            COMPREPLY=( $( compgen -W '--up --down --route --unroute \
 +                --union' -- "$cur" ) )
 +            ;;
 +        ranbits)
 +            COMPREPLY=( $( compgen -W '--quick --continuous --bytes' \
 +                -- "$cur" ) )
 +            ;;
 +        setup)
 +            COMPREPLY=( $( compgen -W '--start --stop --restart' -- "$cur" ) )
 +            ;;
 +        *)
 +            ;;
 +    esac
 +
 +    return 0
 +} &&
 +complete -F _ipsec ipsec
 +
 +# Local variables:
 +# mode: shell-script
 +# sh-basic-offset: 4
 +# sh-indent-comment: t
 +# indent-tabs-mode: nil
 +# End:
 +# ex: ts=4 sw=4 et filetype=sh
diff --combined contrib/lzma
index e015ef8,1846705..a176f19
--- a/contrib/lzma
+++ b/contrib/lzma
@@@ -6,8 -6,7 +6,7 @@@ _lzma(
      local cur prev xspec
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W '-1 -2 -3 -4 -5 -6 -7 -8 -9 \
@@@ -19,7 -18,7 +18,7 @@@
  
      local IFS=$'\t\n'
  
 -    xspec="*.lzma"
 +    xspec="*.@(lzma|tlz)"
      if [[ "$prev" == --* ]]; then
          [[ "$prev" == --decompress || \
              "$prev" == --list || \
diff --combined contrib/man
index c1da66a,c6cac47..a3360b2
--- a/contrib/man
+++ b/contrib/man
@@@ -7,12 -7,11 +7,11 @@@ _man(
  {
      local cur i prev sect manpath manext mansect uname
  
 -    manext="@([0-9lnp]|[0-9][px]|man|3pm)?(.@(gz|bz2|lzma))"
 +    manext="@([0-9lnp]|[0-9][px]|man|3pm)?(.@([gx]z|bz2|lzma|Z))"
      mansect="@([0-9lnp]|[0-9][px]|3pm)"
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      if [[ "$prev" == -l ]]; then
          _filedir $manext
@@@ -54,7 -53,7 +53,7 @@@
      # weed out directory path names and paths to man pages
      COMPREPLY=( ${COMPREPLY[@]##*/?(:)} )
      # strip suffix from man pages
 -    COMPREPLY=( ${COMPREPLY[@]%.@(gz|bz2|lzma)} )
 +    COMPREPLY=( ${COMPREPLY[@]%.@([gx]z|bz2|lzma|Z)} )
      COMPREPLY=( $( compgen -W '${COMPREPLY[@]%.*}' -- "${cur//\\\\/}" ) )
  
      if [[ "$prev" != $mansect ]]; then
diff --combined contrib/module-init-tools
index 5a8994e,0000000..8c0f13e
mode 100644,000000..100644
--- a/contrib/module-init-tools
+++ b/contrib/module-init-tools
@@@ -1,62 -1,0 +1,61 @@@
 +# bash completion for Linux module-init-tools
 +
 +# Linux rmmod(8) completion. This completes on a list of all currently
 +# installed kernel modules.
 +#
 +have rmmod &&
 +_rmmod()
 +{
 +    local cur
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur
 +
 +    _installed_modules "$cur"
 +    return 0
 +} &&
 +complete -F _rmmod rmmod
 +
 +# Linux insmod(8), modprobe(8) and modinfo(8) completion. This completes on a
 +# list of all available modules for the version of the kernel currently
 +# running.
 +#
 +have insmod || have modprobe || have modinfo &&
 +_insmod()
 +{
 +    local cur prev modpath
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
++    _get_comp_words_by_ref cur prev
 +
 +    # behave like lsmod for modprobe -r
 +    if [[ ${1##*/} == modprobe && "${COMP_WORDS[1]}" == -r ]]; then
 +        _installed_modules "$cur"
 +        return 0
 +    fi
 +
 +    # do filename completion if we're giving a path to a module
 +    if [[ "$cur" == */* ]]; then
 +        _filedir '@(?(k)o?(.gz))'
 +        return 0
 +    fi
 +
 +    if [[ $COMP_CWORD -gt 1 && "${COMP_WORDS[COMP_CWORD-1]}" != -* ]]; then
 +        # do module parameter completion
 +        COMPREPLY=( $( compgen -W "$( /sbin/modinfo -p ${COMP_WORDS[1]} | \
 +            cut -d: -f1 )" -- "$cur" ) )
 +    else
 +        _modules $(uname -r)
 +    fi
 +
 +    return 0
 +} &&
 +complete -F _insmod -o filenames insmod modprobe modinfo
 +
 +# Local variables:
 +# mode: shell-script
 +# sh-basic-offset: 4
 +# sh-indent-comment: t
 +# indent-tabs-mode: nil
 +# End:
 +# ex: ts=4 sw=4 et filetype=sh
diff --combined contrib/mount
index a22b078,884494a..b14eef3
--- a/contrib/mount
+++ b/contrib/mount
@@@ -7,93 -7,16 +7,92 @@@
  have mount &&
  {
  
 +# Just like COMPREPLY=(`compgen -W "${COMPREPLY[*]}" -- "$cur"`), only better!
 +#
 +# This will correctly escape special characters in COMPREPLY.
 +_reply_compgen_array()
 +{
 +    # Create the argument for compgen -W by escaping twice.
 +    #
 +    # One round of escape is because we want to reply with escaped arguments. A
 +    # second round is required because compgen -W will helpfully expand it's
 +    # argument.
 +    local i wlist
 +    for i in ${!COMPREPLY[*]}; do
 +        local q=$(quote "$(printf %q "${COMPREPLY[$i]}")")
 +        wlist+=$q$'\n'
 +    done
 +
 +    # We also have to add another round of escaping to $cur.
 +    local ecur="$cur"
 +    ecur="${ecur//\\/\\\\}"
 +    ecur="${ecur//\'/\'}"
 +
 +    # Actually generate completions.
 +    local oldifs=$IFS
 +    IFS=$'\n' eval 'COMPREPLY=(`compgen -W "$wlist" -- "${ecur}"`)'
 +    IFS=$oldifs
 +}
 +
 +# Unescape strings in the linux fstab(5) format (with octal escapes).
 +__linux_fstab_unescape() {
 +    eval $1="'${!1//\'/\047}'"
 +    eval $1="'${!1/%\\/\\\\}'"
 +    eval "$1=$'${!1}'"
 +}
 +
 +# Complete linux fstab entries.
 +#
 +# Reads a file from stdin in the linux fstab(5) format; as used by /etc/fstab
 +# and /proc/mounts.
 +_linux_fstab()
 +{
 +    COMPREPLY=()
 +
 +    # Read and unescape values into COMPREPLY
 +    local fs_spec fs_file fs_other
 +    local oldifs="$IFS"
 +    while read -r fs_spec fs_file fs_other; do
 +        if [[ $fs_spec = [#]* ]]; then continue; fi
 +        if [[ $1 == -L ]]; then
 +            local fs_label=${fs_spec/#LABEL=}
 +            if [[ $fs_label != "$fs_spec" ]]; then
 +                __linux_fstab_unescape fs_label
 +                IFS=$'\0'
 +                COMPREPLY+=("$fs_label")
 +                IFS=$oldifs
 +            fi
 +        else
 +            __linux_fstab_unescape fs_spec
 +            __linux_fstab_unescape fs_file
 +            IFS=$'\0'
 +            [[ $fs_spec = */* ]] && COMPREPLY+=("$fs_spec")
 +            [[ $fs_file = */* ]] && COMPREPLY+=("$fs_file")
 +            IFS=$oldifs
 +        fi
 +    done
 +
 +    _reply_compgen_array
 +}
 +
  _mount()
  {
      local cur sm host prev
  
      COMPREPLY=()
-     cur=`_get_cword ':'`
-     prev=`_get_pword ':'`
+     _get_comp_words_by_ref -n : cur prev
 +
 +    case $prev in
 +        -t|--types)
 +            _fstypes
 +            return 0
 +            ;;
 +    esac
 +
      [[ "$cur" == \\ ]] && cur="/"
  
      if [[ "$cur" == *:* ]]; then
 -        for sm in $(type -P showmount) {,/usr}/{,s}bin/showmount; do
 +        for sm in "$(type -P showmount)" {,/usr}/{,s}bin/showmount; do
              [ -x "$sm" ] || continue
              COMPREPLY=( $( compgen -W "$( "$sm" -e ${cur%%:*} | \
                  awk 'NR>1 {print $1}' )" -- "${cur#*:}" ) )
@@@ -119,12 -42,12 +118,12 @@@
          COMPREPLY=( $( compgen -W "$( mount | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' )" -- "$cur" ) )
      else
          # probably Linux
 -        if [ $prev = -L ]; then
 -            COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*LABEL=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- "$cur" ) )
 -        elif [ $prev = -U ]; then
 +        if [ "$prev" = -L ]; then
 +            _linux_fstab -L < /etc/fstab
 +        elif [ "$prev" = -U ]; then
              COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*UUID=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- "$cur" ) )
          else
 -            COMPREPLY=( $( compgen -W "$( awk '! /^[ \t]*#/ {if ($2 ~ /\//) print $2}' /etc/fstab )" -- "$cur" ) )
 +            _linux_fstab < /etc/fstab
          fi
      fi
  
@@@ -138,18 -61,12 +137,18 @@@ complete -F _mount -o default -o dirnam
  have umount &&
  _umount()
  {
 -    local cur IFS=$'\n'
 -
 -    COMPREPLY=()
++    local cur
+     _get_comp_words_by_ref cur
 +    COMPREPLY=()
  
-     local cur=`_get_cword`
- 
 -    COMPREPLY=( $( compgen -W '$( mount | cut -d" " -f 3 )' -- "$cur" ) )
 +    if [[ $(uname -s) = Linux && -r /proc/mounts ]]; then
 +        # Linux /proc/mounts is properly quoted. This is important when
 +        # unmounting usb devices with pretty names.
 +        _linux_fstab < /proc/mounts
 +    else
 +        local IFS=$'\n'
 +        COMPREPLY=( $( compgen -W '$( mount | cut -d" " -f 3 )' -- "$cur" ) )
 +    fi
  
      return 0
  } &&
diff --combined contrib/mplayer
index ebad58d,0fa133e..63af312
--- a/contrib/mplayer
+++ b/contrib/mplayer
@@@ -15,8 -15,7 +15,7 @@@ _mplayer(
  
      COMPREPLY=()
      cmd=${COMP_WORDS[0]}
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -[av][cfo]|-[av]fm|-vop|-fstype|-demuxer|-o[av]c|-of|-profile)
@@@ -237,7 -236,7 +236,7 @@@
                      -e "/^-\(Total\|.*\*\)\{0,1\}$/!p" )' -- "$cur" ) )
              ;;
          *)
 -            _filedir '@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|ASF|vob|VOB|bin|BIN|dat|DAT|vcd|VCD|ps|PS|pes|PES|fl[iv]|FL[IV]|viv|VIV|rm?(j)|RM?(J)|ra?(m)|RA?(M)|yuv|YUV|mov|MOV|qt|QT|mp[234]|MP[234]|m4[av]|M4[AV]|og[gmavx]|OG[GMAVX]|w?(a)v|W?(A)V|dump|DUMP|mk[av]|MK[AV]|m4a|M4A|aac|AAC|m[24]v|M[24]V|dv|DV|rmvb|RMVB|mid|MID|ts|TS|3g[p2]|mpc|MPC|flac|FLAC|vro|VRO|divx|DIVX|aif?(f)|AIF?(F)|m2ts|M2TS|vdr|VDR|xvid|XVID|ape|APE)'
 +            _filedir '@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|ASF|vob|VOB|bin|BIN|dat|DAT|vcd|VCD|ps|PS|pes|PES|fl[iv]|FL[IV]|fxm|FXM|viv|VIV|rm?(j)|RM?(J)|ra?(m)|RA?(M)|yuv|YUV|mov|MOV|qt|QT|mp[234]|MP[234]|m4[av]|M4[AV]|og[gmavx]|OG[GMAVX]|w?(a)v|W?(A)V|dump|DUMP|mk[av]|MK[AV]|m4a|M4A|aac|AAC|m[24]v|M[24]V|dv|DV|rmvb|RMVB|mid|MID|t[ps]|T[PS]|3g[p2]|mpc|MPC|flac|FLAC|vro|VRO|divx|DIVX|aif?(f)|AIF?(F)|m2ts|M2TS|vdr|VDR|xvid|XVID|ape|APE)'
              ;;
      esac
  
diff --combined contrib/perl
index af85d8f,e9e7e46..67996f9
--- a/contrib/perl
+++ b/contrib/perl
@@@ -14,8 -14,7 +14,7 @@@ _perl(
      local optPrefix optSuffix
  
      COMPREPLY=()
-     cur=`_get_cword :`
-     prev=`_get_pword :`
+     _get_comp_words_by_ref -n : cur prev
      prefix=""
  
      # If option not followed by whitespace, reassign prev and cur
@@@ -55,8 -54,7 +54,7 @@@ _perldoc(
      local cur prev prefix temp
  
      COMPREPLY=()
-     cur=`_get_cword :`
-     prev=`_get_pword :`
+     _get_comp_words_by_ref -n : cur prev
      prefix=""
  
      # completing an option (may or may not be separated by a space)
@@@ -77,14 -75,14 +75,14 @@@
                  shift splice unshift grep join map qw reverse sort unpack \
                  delete each exists keys values binmode close closedir \
                  dbmclose dbmopen die eof fileno flock format getc print \
 -                printf read readdir rewinddir seek seekdir select syscall \
 +                printf read readdir rewinddir say seek seekdir select syscall \
                  sysread sysseek syswrite tell telldir truncate warn write \
                  pack read syscall sysread syswrite unpack vec -X chdir chmod \
                  chown chroot fcntl glob ioctl link lstat mkdir open opendir \
                  readlink rename rmdir stat symlink umask unlink utime caller \
                  continue do dump eval exit goto last next redo return \
 -                sub wantarray caller import local my our package use defined \
 -                formline reset scalar undef \
 +                sub wantarray break caller import local my our state package \
 +                use defined formline reset scalar undef \
                  alarm exec fork getpgrp getppid getpriority kill pipe qx \
                  setpgrp setpriority sleep system times wait waitpid \
                  import no package require use bless dbmclose dbmopen package \
@@@ -98,7 -96,7 +96,7 @@@
                  getnetbyaddr getnetbyname getnetent getprotobyname \
                  getprotobynumber getprotoent getservbyname getservbyport \
                  getservent sethostent setnetent setprotoent setservent \
 -                gmtime localtime time times' -- "$cur" ) )
 +                gmtime localtime time times lock' -- "$cur" ) )
              return 0
              ;;
      esac
@@@ -114,10 -112,9 +112,10 @@@
                  sed -ne "/perl.*Perl overview/,/perlwin32/p" | \
                  awk "\$NF=2 { print \$1}" | command grep perl )' -- "$cur" ) )
          fi
 +        _filedir '@(pl|PL|pm|PM|pod|POD)'
      fi
  }
 -complete -F _perldoc -o default perldoc
 +complete -F _perldoc -o bashdefault perldoc
  }
  
  # Local variables:
diff --combined contrib/pkgtools
index 87cd40e,eb76cb9..3a5df27
--- a/contrib/pkgtools
+++ b/contrib/pkgtools
@@@ -6,12 -6,12 +6,12 @@@ _removepkg(
      local packages cur
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      COMPREPLY=( $( (cd /var/log/packages; compgen -f -- "$cur") ) )
  } &&
  complete -F _removepkg -o filenames removepkg &&
 -    complete -o dirnames -f -X '!*.tgz' installpkg upgradepkg explodepkg
 +    complete -o dirnames -f -X '!*.t[bglx]z' installpkg upgradepkg explodepkg
  
  # Local variables:
  # mode: shell-script
diff --combined contrib/procps
index 4a141f2,0000000..db8fc3d
mode 100644,000000..100644
--- a/contrib/procps
+++ b/contrib/procps
@@@ -1,49 -1,0 +1,49 @@@
 +# Completions for tools included in procps and related
 +
 +# killall(1) (Linux and FreeBSD) and pkill(1) completion.
 +#
 +[[ $UNAME == Linux || $UNAME == FreeBSD ]] || have pkill &&
 +_killall()
 +{
 +    local cur
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur
 +
 +    if [[ $COMP_CWORD -eq 1 && "$cur" == -* ]]; then
 +        _signals
 +    else
 +        _pnames
 +    fi
 +
 +    return 0
 +}
 +[[ $UNAME == Linux || $UNAME == FreeBSD ]] && complete -F _killall killall
 +have pkill && complete -F _killall pkill
 +
 +# pgrep(1) completion.
 +#
 +[ $UNAME = Linux ] || have pgrep &&
 +_pgrep()
 +{
 +    local cur
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur
 +
 +    _pnames
 +
 +    return 0
 +}
 +have pgrep && complete -F _pgrep pgrep
 +
 +# Linux pidof(8) completion.
 +[ $UNAME = Linux ] && complete -F _pgrep pidof
 +
 +# Local variables:
 +# mode: shell-script
 +# sh-basic-offset: 4
 +# sh-indent-comment: t
 +# indent-tabs-mode: nil
 +# End:
 +# ex: ts=4 sw=4 et filetype=sh
diff --combined contrib/rsync
index 31324e5,1c37ec2..b0f2d10
--- a/contrib/rsync
+++ b/contrib/rsync
@@@ -6,8 -6,8 +6,8 @@@ _rsync(
      # TODO: _split_longopt
  
      COMPREPLY=()
-     local cur=`_get_cword :`
-     local prev=`_get_pword :`
+     local cur prev
+     _get_comp_words_by_ref -n : cur prev
  
      _expand || return 0
  
@@@ -32,10 -32,10 +32,10 @@@
  
      case $cur in
          -*)
 -            COMPREPLY=( $( compgen -W '--verbose --quiet --checksum --no-motd \
 -                --checksum --archive --recursive --relative --no-implied-dirs \
 +            COMPREPLY=( $( compgen -W '--verbose --quiet --no-motd --checksum \
 +                --archive --recursive --relative --no-implied-dirs \
                  --backup --backup-dir --suffix= --update --inplace --append \
 -                --append-verify --dirs --links --copy-links \
 +                --append-verify --dirs --old-dirs --links --copy-links \
                  --copy-unsafe-links --safe-links --copy-dirlinks \
                  --keep-dirlinks --hard-links --perms --executability --chmod= \
                  --acls --xattrs --owner --group --devices --copy-devices \
@@@ -51,7 -51,7 +51,7 @@@
                  --temp-dir= --fuzzy --compare-dest= --copy-dest= --link-dest= \
                  --compress --compress-level= --skip-compress= --cvs-exclude \
                  --filter= --exclude= --exclude-from= --include= \
 -                --include-from= --files-from= --from0 --protect-args
 +                --include-from= --files-from= --from0 --protect-args \
                  --address= --port= --sockopts= --blocking-io --no-blocking-io \
                  --stats --8-bit-output --human-readable --progress \
                  --itemize-changes --out-format= --log-file= \
diff --combined contrib/screen
index faed765,721c076..cabc4b7
--- a/contrib/screen
+++ b/contrib/screen
@@@ -16,20 -16,17 +16,19 @@@ _screen_sessions(
  } &&
  _screen()
  {
-     local cur prev preprev
+     local cur prev words cword
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+     _get_comp_words_by_ref cur prev words cword
  
-     [ "$COMP_CWORD" -ge 2 ] && preprev=${COMP_WORDS[COMP_CWORD-2]}
- 
-     case $preprev in
-         -[dD])
-             _screen_sessions
-             return 0
-             ;;
-     esac
 -    case ${words[cwords-2]} in
 -        -[dD])
 -            _screen_sessions
 -            return 0
 -            ;;
 -    esac
++    if ((cword > 2)); then
++        case ${words[cword-2]} in
++            -[dD])
++                _screen_sessions
++                return 0
++                ;;
++        esac
++    fi
  
      case $prev in
          -[rR])
diff --combined contrib/service
index 1c48075,0000000..9ebd117
mode 100644,000000..100644
--- a/contrib/service
+++ b/contrib/service
@@@ -1,46 -1,0 +1,45 @@@
 +# service(8) and /etc/init.d/* completion
 +
 +# This completes on a list of all available service scripts for the
 +# 'service' command and/or the SysV init.d directory, followed by
 +# that script's available commands
 +#
 +{ have service || [ -d /etc/init.d/ ]; } &&
 +_service()
 +{
 +    local cur prev sysvdir
 +
 +    COMPREPLY=()
-     prev=${COMP_WORDS[COMP_CWORD-1]}
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur prev
 +
 +    # don't complete for things like killall, ssh and mysql if it's
 +    # the standalone command, rather than the init script
 +    [[ ${COMP_WORDS[0]} != @(*init.d/!(functions|~)|service) ]] && return 0
 +
 +    # don't complete past 2nd token
 +    [ $COMP_CWORD -gt 2 ] && return 0
 +
 +    [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d || sysvdir=/etc/init.d
 +
 +    if [[ $COMP_CWORD -eq 1 ]] && [[ $prev == "service" ]]; then
 +        _services
 +    else
 +        COMPREPLY=( $( compgen -W '`sed -e "y/|/ /" \
 +            -ne "s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \
 +            $sysvdir/${prev##*/} 2>/dev/null`' -- "$cur" ) )
 +    fi
 +
 +    return 0
 +} &&
 +complete -F _service service
 +[ -d /etc/init.d/ ] && complete -F _service -o default \
 +    $(for i in /etc/init.d/*; do
 +    complete -p ${i##*/} &>/dev/null || printf '%s\n' ${i##*/}; done)
 +
 +# Local variables:
 +# mode: shell-script
 +# sh-basic-offset: 4
 +# sh-indent-comment: t
 +# indent-tabs-mode: nil
 +# End:
 +# ex: ts=4 sw=4 et filetype=sh
diff --combined contrib/ssh
index 86f2129,229ca2a..b4bafde
--- a/contrib/ssh
+++ b/contrib/ssh
@@@ -6,10 -6,8 +6,10 @@@ have ssh &
  _ssh_bindaddress()
  {
      COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W \
 -        "$( PATH="$PATH:/sbin" ifconfig | \
 -        sed -ne 's/.*addr:\([^[:space:]]*\).*/\1/p' )" -- "$cur" ) )
 +        "$( PATH="$PATH:/sbin" ifconfig -a | \
 +        sed -ne 's/.*addr:\([^[:space:]]*\).*/\1/p' \
 +            -ne 's/.*inet[[:space:]]\{1,\}\([^[:space:]]*\).*/\1/p' )" \
 +        -- "$cur" ) )
  }
  
  _ssh_ciphers()
@@@ -120,8 -118,9 +120,9 @@@ _ssh(
      local -a config
  
      COMPREPLY=()
-     cur=`_get_cword :`
-     prev=`_get_pword`
+     _get_comp_words_by_ref -n : cur prev
+     #cur=`_get_cword :`
+     #prev=`_get_pword`
  
      _ssh_suboption_check && return 0
  
@@@ -198,8 -197,7 +199,7 @@@ _sftp(
      local cur prev configfile
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=`_get_pword`
+     _get_comp_words_by_ref cur prev
  
      _ssh_suboption_check && return 0
  
@@@ -316,8 -314,7 +316,7 @@@ _scp(
      local configfile cur prev prefix
  
      COMPREPLY=()
-     cur=`_get_cword ":"`
-     prev=`_get_pword ":"`
+     _get_comp_words_by_ref -n : cur prev
  
      _ssh_suboption_check && {
          COMPREPLY=( "${COMPREPLY[@]/%/ }" )
@@@ -399,8 -396,7 +398,7 @@@ _ssh_copy_id(
      local cur prev
  
      COMPREPLY=()
-     cur=`_get_cword`
-     prev=`_get_pword`
+     _get_comp_words_by_ref cur prev
  
      case $prev in
          -i)
diff --combined contrib/tar
index 8f4fc54,db6e7c9..400daa6
--- a/contrib/tar
+++ b/contrib/tar
@@@ -6,7 -6,7 +6,7 @@@ _tar(
      local cur ext regex tar untar
  
      COMPREPLY=()
-     cur=`_get_cword`
+     _get_comp_words_by_ref cur
  
      if [ $COMP_CWORD -eq 1 ]; then
          COMPREPLY=( $( compgen -W 'c t x u r d A' -- "$cur" ) )
@@@ -19,7 -19,7 +19,7 @@@
          return 0
          ;;
      +([^IZzJjy])f)
 -        ext='t@(ar?(.@(Z|gz|bz?(2)|lz?(ma)))|gz|bz?(2)|lz?(ma))'
 +        ext='t@(ar?(.@(Z|gz|bz?(2)|lz?(ma)|xz))|gz|bz?(2)|lz?(ma)|xz)'
          regex='t\(ar\(\.\(Z\|gz\|bz2\?\|lzma\|xz\)\)\?\|gz\|bz2\?\|lzma\|xz\)'
          ;;
      *[Zz]*f)
diff --combined contrib/util-linux
index 1ac900f,0000000..8017ebb
mode 100644,000000..100644
--- a/contrib/util-linux
+++ b/contrib/util-linux
@@@ -1,76 -1,0 +1,76 @@@
 +# Completions for tools included in util-linux (not necessarily Linux specific)
 +
 +# renice(8) completion
 +#
 +have renice &&
 +_renice()
 +{
 +    local command cur curopt i
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur
 +    command=$1
 +
 +    i=0
 +    # walk back through command line and find last option
 +    while [[ $i -le $COMP_CWORD && ${#COMPREPLY[@]} -eq 0 ]]; do
 +        curopt=${COMP_WORDS[COMP_CWORD-$i]}
 +        case "$curopt" in
 +            -u)
 +                COMPREPLY=( $( compgen -u -- "$cur" ) )
 +                ;;
 +            -g)
 +                _pgids
 +                ;;
 +            -p|$command)
 +                _pids
 +                ;;
 +        esac
 +        i=$(( ++i ))
 +    done
 +} &&
 +complete -F _renice renice
 +
 +# kill(1) completion
 +#
 +have kill &&
 +_kill()
 +{
 +    local cur
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur
 +
 +    if [[ $COMP_CWORD -eq 1 && "$cur" == -* ]]; then
 +        # return list of available signals
 +        _signals
 +    else
 +        # return list of available PIDs
 +        _pids
 +    fi
 +} &&
 +complete -F _kill kill
 +
 +# look(1) completion
 +#
 +have look &&
 +_look()
 +{
 +    local cur
 +
 +    COMPREPLY=()
-     cur=`_get_cword`
++    _get_comp_words_by_ref cur
 +
 +    if [ $COMP_CWORD = 1 ]; then
 +        COMPREPLY=( $( compgen -W '$(look "$cur" 2>/dev/null)' -- "$cur" ) )
 +    fi
 +} &&
 +complete -F _look -o default look
 +
 +# Local variables:
 +# mode: shell-script
 +# sh-basic-offset: 4
 +# sh-indent-comment: t
 +# indent-tabs-mode: nil
 +# End:
 +# ex: ts=4 sw=4 et filetype=sh
diff --combined contrib/xhost
index 84981d8,36ddb09..cec4adc
--- a/contrib/xhost
+++ b/contrib/xhost
@@@ -3,7 -3,8 +3,8 @@@
  have xhost &&
  _xhost ()
  {
-     local cur=`_get_cword`
+     local cur
+     _get_comp_words_by_ref cur
  
      case $cur in
          +*) _known_hosts_real -p+ "${cur:1}" ;;
@@@ -12,7 -13,7 +13,7 @@@
      esac
  
      return 0
 -}
 +} &&
  complete -F _xhost xhost
  
  # Local variables:
diff --combined contrib/xz
index 3a543f3,a44a21e..46420b0
--- a/contrib/xz
+++ b/contrib/xz
@@@ -4,8 -4,8 +4,8 @@@ have xz &
  _xz()
  {
      COMPREPLY=()
-     local cur=`_get_cword`
-     local prev=${COMP_WORDS[COMP_CWORD-1]}
+     local cur prev
+     _get_comp_words_by_ref cur prev
  
      if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W '--compress --decompress --test --list \
@@@ -20,10 -20,10 +20,10 @@@
      local split=false
      _split_longopt && split=true
  
 -    local xspec="*.@(xz|lzma)"
 +    local xspec="*.@(xz|lzma|txz|tlz)"
  
      case $prev in
 -        --decompress|--list|--test|!(-*)[dlt]*)
 +        --decompress|--list|--test|-!(-*)[dlt]*)
              xspec="!"$xspec
              ;;
          --files|--files0)
@@@ -64,8 -64,8 +64,8 @@@ have xzdec &
  _xzdec()
  {
      COMPREPLY=()
-     local cur=`_get_cword`
-     local prev=${COMP_WORDS[COMP_CWORD-1]}
+     local cur prev
+     _get_comp_words_by_ref cur prev
  
      if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W '--memory --help --version' -- "$cur" ) )

-- 
bash-completion



More information about the Bash-completion-commits mailing list