Lekensteyn

/etc/bash_completion

Jul 28th, 2011
385
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 59.03 KB | None | 0 0
  1. #
  2. #   bash_completion - programmable completion functions for bash 3.2+
  3. #
  4. #   Copyright © 2006-2008, Ian Macdonald <[email protected]>
  5. #             © 2009-2011, Bash Completion Maintainers
  6. #                     <[email protected]>
  7. #
  8. #   This program is free software; you can redistribute it and/or modify
  9. #   it under the terms of the GNU General Public License as published by
  10. #   the Free Software Foundation; either version 2, or (at your option)
  11. #   any later version.
  12. #
  13. #   This program is distributed in the hope that it will be useful,
  14. #   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. #   GNU General Public License for more details.
  17. #
  18. #   You should have received a copy of the GNU General Public License
  19. #   along with this program; if not, write to the Free Software Foundation,
  20. #   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. #
  22. #   The latest version of this software can be obtained here:
  23. #
  24. #   http://bash-completion.alioth.debian.org/
  25. #
  26. #   RELEASE: 1.3
  27.  
  28. if [[ $- == *v* ]]; then
  29.     BASH_COMPLETION_ORIGINAL_V_VALUE="-v"
  30. else
  31.     BASH_COMPLETION_ORIGINAL_V_VALUE="+v"
  32. fi
  33.  
  34. if [[ -n $BASH_COMPLETION_DEBUG ]]; then
  35.     set -v
  36. else
  37.     set +v
  38. fi
  39.  
  40. # Alter the following to reflect the location of this file.
  41. #
  42. [ -n "$BASH_COMPLETION" ] || BASH_COMPLETION=/etc/bash_completion
  43. [ -n "$BASH_COMPLETION_DIR" ] || BASH_COMPLETION_DIR=/etc/bash_completion.d
  44. [ -n "$BASH_COMPLETION_COMPAT_DIR" ] || BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
  45. readonly BASH_COMPLETION BASH_COMPLETION_DIR BASH_COMPLETION_COMPAT_DIR
  46.  
  47. # Set a couple of useful vars
  48. #
  49. UNAME=$( uname -s )
  50. # strip OS type and version under Cygwin (e.g. CYGWIN_NT-5.1 => Cygwin)
  51. UNAME=${UNAME/CYGWIN_*/Cygwin}
  52.  
  53. case ${UNAME} in
  54.     Linux|GNU|GNU/*) USERLAND=GNU ;;
  55.     *) USERLAND=${UNAME} ;;
  56. esac
  57.  
  58. # Turn on extended globbing and programmable completion
  59. shopt -s extglob progcomp
  60.  
  61. # A lot of the following one-liners were taken directly from the
  62. # completion examples provided with the bash 2.04 source distribution
  63.  
  64. # Make directory commands see only directories
  65. complete -d pushd
  66.  
  67. # The following section lists completions that are redefined later
  68. # Do NOT break these over multiple lines.
  69. #
  70. # START exclude -- do NOT remove this line
  71. # bzcmp, bzdiff, bz*grep, bzless, bzmore intentionally not here, see Debian: #455510
  72. complete -f -X '!*.?(t)bz?(2)' bunzip2 bzcat pbunzip2 pbzcat
  73. complete -f -X '!*.@(zip|[ejw]ar|exe|pk3|wsz|zargo|xpi|sxw|o[tx]t|od[fgpst]|epub|apk)' unzip zipinfo
  74. complete -f -X '*.Z' compress znew
  75. # zcmp, zdiff, z*grep, zless, zmore intentionally not here, see Debian: #455510
  76. complete -f -X '!*.@(Z|[gGd]z|t[ag]z)' gunzip zcat unpigz
  77. complete -f -X '!*.Z' uncompress
  78. # lzcmp, lzdiff intentionally not here, see Debian: #455510
  79. complete -f -X '!*.@(tlz|lzma)' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma
  80. complete -f -X '!*.@(?(t)xz|tlz|lzma)' unxz xzcat
  81. complete -f -X '!*.lrz' lrunzip
  82. complete -f -X '!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx)' ee
  83. complete -f -X '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm)' xv qiv
  84. complete -f -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview
  85. complete -f -X '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi kdvi
  86. complete -f -X '!*.dvi' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx
  87. complete -f -X '!*.[pf]df' acroread gpdf xpdf
  88. complete -f -X '!*.@(?(e)ps|pdf)' kpdf
  89. complete -f -X '!*.@(@(?(e)ps|?(E)PS|[pf]df|[PF]DF|dvi|DVI)?(.gz|.GZ|.bz2|.BZ2)|cb[rz]|djv?(u)|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|fdf)' evince
  90. 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?(2)|FB?(2)|mobi|MOBI|g3|G3|chm|CHM|fdf|FDF)?(.?(gz|GZ|bz2|BZ2)))' okular
  91. complete -f -X '!*.@(?(e)ps|pdf)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr
  92. complete -f -X '!*.texi*' makeinfo texi2html
  93. complete -f -X '!*.@(?(la)tex|texi|dtx|ins|ltx)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi
  94. complete -f -X '!*.mp3' mpg123 mpg321 madplay
  95. 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]|m2t?(s)|M2T?(S)|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))?(.part)' xine aaxine fbxine
  96. 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]|m2t?(s)|M2T?(S)|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|iso|ISO)|+([0-9]).@(vdr|VDR))?(.part)' kaffeine dragon
  97. complete -f -X '!*.@(avi|asf|wmv)' aviplay
  98. complete -f -X '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay
  99. complete -f -X '!*.@(mpg|mpeg|avi|mov|qt)' xanim
  100. complete -f -X '!*.@(ogg|m3u|flac|spx)' ogg123
  101. complete -f -X '!*.@(mp3|ogg|pls|m3u)' gqmpeg freeamp
  102. complete -f -X '!*.fig' xfig
  103. complete -f -X '!*.@(mid?(i)|cmf)' playmidi
  104. complete -f -X '!*.@(mid?(i)|rmi|rcp|[gr]36|g18|mod|xm|it|x3m|s[3t]m|kar)' timidity
  105. complete -f -X '!*.@(m[eo]d|s[3t]m|xm|it)' modplugplay modplug123
  106. complete -f -X '*.@(o|so|so.!(conf)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite
  107. complete -f -X '!*.@([eE][xX][eE]?(.[sS][oO])|[cC][oO][mM]|[sS][cC][rR])' wine
  108. complete -f -X '!*.@(zip|z|gz|tgz)' bzme
  109. # konqueror not here on purpose, it's more than a web/html browser
  110. 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
  111. complete -f -X '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|odt|ott|odm)' oowriter
  112. complete -f -X '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|odp|otp)' ooimpress
  113. complete -f -X '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|ods|ots)' oocalc
  114. complete -f -X '!*.@(sxd|std|sda|sdd|odg|otg)' oodraw
  115. complete -f -X '!*.@(sxm|smf|mml|odf)' oomath
  116. complete -f -X '!*.odb' oobase
  117. complete -f -X '!*.[rs]pm' rpm2cpio
  118. complete -f -X '!*.aux' bibtex
  119. complete -f -X '!*.po' poedit gtranslator kbabel lokalize
  120. complete -f -X '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp
  121. complete -f -X '!*.[Hh][Rr][Bb]' hbrun
  122. complete -f -X '!*.ly' lilypond ly2dvi
  123. complete -f -X '!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))' cdiff
  124. complete -f -X '!*.lyx' lyx
  125. complete -f -X '!@(*.@(ks|jks|jceks|p12|pfx|bks|ubr|gkr|cer|crt|cert|p7b|pkipath|pem|p10|csr|crl)|cacerts)' portecle
  126. complete -f -X '!*.@(mp[234c]|og[ag]|@(fl|a)ac|m4[abp]|spx|tta|w?(a)v|wma|aif?(f)|asf|ape)' kid3 kid3-qt
  127. # FINISH exclude -- do not remove this line
  128.  
  129. # start of section containing compspecs that can be handled within bash
  130.  
  131. # user commands see only users
  132. complete -u su write chfn groups slay w sux runuser
  133.  
  134. # bg completes with stopped jobs
  135. complete -A stopped -P '"%' -S '"' bg
  136.  
  137. # other job commands
  138. complete -j -P '"%' -S '"' fg jobs disown
  139.  
  140. # readonly and unset complete with shell variables
  141. complete -v readonly unset
  142.  
  143. # set completes with set options
  144. complete -A setopt set
  145.  
  146. # shopt completes with shopt options
  147. complete -A shopt shopt
  148.  
  149. # helptopics
  150. complete -A helptopic help
  151.  
  152. # unalias completes with aliases
  153. complete -a unalias
  154.  
  155. # bind completes with readline bindings (make this more intelligent)
  156. complete -A binding bind
  157.  
  158. # type and which complete on commands
  159. complete -c command type which
  160.  
  161. # builtin completes on builtins
  162. complete -b builtin
  163.  
  164. # start of section containing completion functions called by other functions
  165.  
  166. # This function checks whether we have a given program on the system.
  167. # No need for bulky functions in memory if we don't.
  168. #
  169. have()
  170. {
  171.     unset -v have
  172.     # Completions for system administrator commands are installed as well in
  173.     # case completion is attempted via `sudo command ...'.
  174.     PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 &>/dev/null &&
  175.     have="yes"
  176. }
  177.  
  178. # This function checks whether a given readline variable
  179. # is `on'.
  180. #
  181. _rl_enabled()
  182. {
  183.     [[ "$( bind -v )" = *$1+([[:space:]])on* ]]
  184. }
  185.  
  186. # This function shell-quotes the argument
  187. quote()
  188. {
  189.     echo \'${1//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
  190. }
  191.  
  192. # @see _quote_readline_by_ref()
  193. quote_readline()
  194. {
  195.     local quoted
  196.     _quote_readline_by_ref "$1" ret
  197.     printf %s "$ret"
  198. } # quote_readline()
  199.  
  200.  
  201. # This function shell-dequotes the argument
  202. dequote()
  203. {
  204.     eval echo "$1" 2> /dev/null
  205. }
  206.  
  207.  
  208. # Assign variable one scope above the caller
  209. # Usage: local "$1" && _upvar $1 "value(s)"
  210. # Param: $1  Variable name to assign value to
  211. # Param: $*  Value(s) to assign.  If multiple values, an array is
  212. #            assigned, otherwise a single value is assigned.
  213. # NOTE: For assigning multiple variables, use '_upvars'.  Do NOT
  214. #       use multiple '_upvar' calls, since one '_upvar' call might
  215. #       reassign a variable to be used by another '_upvar' call.
  216. # See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
  217. _upvar() {
  218.     if unset -v "$1"; then           # Unset & validate varname
  219.         if (( $# == 2 )); then
  220.             eval $1=\"\$2\"          # Return single value
  221.         else
  222.             eval $1=\(\"\${@:2}\"\)  # Return array
  223.         fi
  224.     fi
  225. }
  226.  
  227.  
  228. # Assign variables one scope above the caller
  229. # Usage: local varname [varname ...] &&
  230. #        _upvars [-v varname value] | [-aN varname [value ...]] ...
  231. # Available OPTIONS:
  232. #     -aN  Assign next N values to varname as array
  233. #     -v   Assign single value to varname
  234. # Return: 1 if error occurs
  235. # See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
  236. _upvars() {
  237.     if ! (( $# )); then
  238.         echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
  239.             "value] | [-aN varname [value ...]] ..." 1>&2
  240.         return 2
  241.     fi
  242.     while (( $# )); do
  243.         case $1 in
  244.             -a*)
  245.                 # Error checking
  246.                 [[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1': missing"\
  247.                    "number specifier" 1>&2; return 1; }
  248.                printf %d "${1#-a}" &> /dev/null || { echo "bash:"\
  249.                    "${FUNCNAME[0]}: \`$1': invalid number specifier" 1>&2
  250.                     return 1; }
  251.                 # Assign array of -aN elements
  252.                 [[ "$2" ]] && unset -v "$2" && eval $2=\(\"\${@:3:${1#-a}}\"\) &&
  253.                 shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:"\
  254.                     "\`$1${2+ }$2': missing argument(s)" 1>&2; return 1; }
  255.                ;;
  256.            -v)
  257.                # Assign single value
  258.                [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
  259.                shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\
  260.                "argument(s)" 1>&2; return 1; }
  261.                ;;
  262.            *)
  263.                echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2
  264.                return 1 ;;
  265.        esac
  266.    done
  267. }
  268.  
  269.  
  270. # Reassemble command line words, excluding specified characters from the
  271. # list of word completion separators (COMP_WORDBREAKS).
  272. # @param $1 chars  Characters out of $COMP_WORDBREAKS which should
  273. #     NOT be considered word breaks. This is useful for things like scp where
  274. #     we want to return host:path and not only path, so we would pass the
  275. #     colon (:) as $1 here.
  276. # @param $2 words  Name of variable to return words to
  277. # @param $3 cword  Name of variable to return cword to
  278. #
  279. __reassemble_comp_words_by_ref() {
  280.    local exclude i j ref
  281.    # Exclude word separator characters?
  282.    if [[ $1 ]]; then
  283.        # Yes, exclude word separator characters;
  284.        # Exclude only those characters, which were really included
  285.        exclude="${1//[^$COMP_WORDBREAKS]}"
  286.    fi
  287.        
  288.    # Default to cword unchanged
  289.    eval $3=$COMP_CWORD
  290.    # Are characters excluded which were former included?
  291.    if [[ $exclude ]]; then
  292.        # Yes, list of word completion separators has shrunk;
  293.        # Re-assemble words to complete
  294.        for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
  295.            # Is current word not word 0 (the command itself) and is word not
  296.            # empty and is word made up of just word separator characters to be
  297.            # excluded?
  298.            while [[ $i -gt 0 && ${COMP_WORDS[$i]} &&
  299.                ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]}
  300.            ]]; do
  301.                [ $j -ge 2 ] && ((j--))
  302.                # Append word separator to current word
  303.                ref="$2[$j]"
  304.                eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
  305.                # Indicate new cword
  306.                [ $i = $COMP_CWORD ] && eval $3=$j
  307.                # Indicate next word if available, else end *both* while and for loop
  308.                (( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
  309.            done
  310.            # Append word to current word
  311.            ref="$2[$j]"
  312.            eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
  313.            # Indicate new cword
  314.            [[ $i == $COMP_CWORD ]] && eval $3=$j
  315.        done
  316.    else
  317.        # No, list of word completions separators hasn't changed;
  318.        eval $2=\( \"\${COMP_WORDS[@]}\" \)
  319.    fi
  320. } # __reassemble_comp_words_by_ref()
  321.  
  322.  
  323. # @param $1 exclude  Characters out of $COMP_WORDBREAKS which should NOT be
  324. #     considered word breaks. This is useful for things like scp where
  325. #     we want to return host:path and not only path, so we would pass the
  326. #     colon (:) as $1 in this case.  Bash-3 doesn't do word splitting, so this
  327. #     ensures we get the same word on both bash-3 and bash-4.
  328. # @param $2 words  Name of variable to return words to
  329. # @param $3 cword  Name of variable to return cword to
  330. # @param $4 cur  Name of variable to return current word to complete to
  331. # @see ___get_cword_at_cursor_by_ref()
  332. __get_cword_at_cursor_by_ref() {
  333.    local cword words=()
  334.    __reassemble_comp_words_by_ref "$1" words cword
  335.  
  336.    local i cur2
  337.    local cur="$COMP_LINE"
  338.    local index="$COMP_POINT"
  339.    for (( i = 0; i <= cword; ++i )); do
  340.        while [[
  341.            # Current word fits in $cur?
  342.            "${#cur}" -ge ${#words[i]} &&
  343.            # $cur doesn't match cword?
  344.            "${cur:0:${#words[i]}}" != "${words[i]}"
  345.        ]]; do
  346.            # Strip first character
  347.            cur="${cur:1}"
  348.            # Decrease cursor position
  349.            ((index--))
  350.        done
  351.  
  352.        # Does found word matches cword?
  353.        if [[ "$i" -lt "$cword" ]]; then
  354.            # No, cword lies further;
  355.            local old_size="${#cur}"
  356.            cur="${cur#${words[i]}}"
  357.            local new_size="${#cur}"
  358.            index=$(( index - old_size + new_size ))
  359.        fi
  360.    done
  361.  
  362.    if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
  363.        # We messed up. At least return the whole word so things keep working
  364.        cur2=${words[cword]}
  365.    else
  366.        cur2=${cur:0:$index}
  367.    fi
  368.  
  369.    local "$2" "$3" "$4" &&
  370.        _upvars -a${#words[@]} $2 "${words[@]}" -v $3 "$cword" -v $4 "$cur2"
  371. }
  372.  
  373.  
  374. # Get the word to complete and optional previous words.
  375. # This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
  376. # where the user is completing in the middle of a word.
  377. # (For example, if the line is "ls foobar",
  378. # and the cursor is here -------->   ^
  379. # Also one is able to cross over possible wordbreak characters.
  380. # Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
  381. # Available VARNAMES:
  382. #     cur         Return cur via $cur
  383. #     prev        Return prev via $prev
  384. #     words       Return words via $words
  385. #     cword       Return cword via $cword
  386. #
  387. # Available OPTIONS:
  388. #     -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT be
  389. #                 considered word breaks. This is useful for things like scp
  390. #                 where we want to return host:path and not only path, so we
  391. #                 would pass the colon (:) as -n option in this case.  Bash-3
  392. #                 doesn't do word splitting, so this ensures we get the same
  393. #                 word on both bash-3 and bash-4.
  394. #     -c VARNAME  Return cur via $VARNAME
  395. #     -p VARNAME  Return prev via $VARNAME
  396. #     -w VARNAME  Return words via $VARNAME
  397. #     -i VARNAME  Return cword via $VARNAME
  398. #
  399. # Example usage:
  400. #
  401. #    $ _get_comp_words_by_ref -n : cur prev
  402. #
  403. _get_comp_words_by_ref()
  404. {
  405.    local exclude flag i OPTIND=1
  406.    local cur cword words=()
  407.    local upargs=() upvars=() vcur vcword vprev vwords
  408.  
  409.    while getopts "c:i:n:p:w:" flag "$@"; do
  410.        case $flag in
  411.            c) vcur=$OPTARG ;;
  412.            i) vcword=$OPTARG ;;
  413.            n) exclude=$OPTARG ;;
  414.            p) vprev=$OPTARG ;;
  415.            w) vwords=$OPTARG ;;
  416.        esac
  417.    done
  418.    while [[ $# -ge $OPTIND ]]; do
  419.        case ${!OPTIND} in
  420.            cur)   vcur=cur ;;
  421.            prev)  vprev=prev ;;
  422.            cword) vcword=cword ;;
  423.            words) vwords=words ;;
  424.            *) echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" \
  425.                 1>&2; return 1
  426.         esac
  427.         let "OPTIND += 1"
  428.     done
  429.  
  430.     __get_cword_at_cursor_by_ref "$exclude" words cword cur
  431.  
  432.     [[ $vcur   ]] && { upvars+=("$vcur"  ); upargs+=(-v $vcur   "$cur"  ); }
  433.     [[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
  434.     [[ $vprev  ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev
  435.         "${words[cword - 1]}"); }
  436.     [[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
  437.         "${words[@]}"); }
  438.  
  439.     (( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
  440. }
  441.  
  442.  
  443. # Get the word to complete.
  444. # This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
  445. # where the user is completing in the middle of a word.
  446. # (For example, if the line is "ls foobar",
  447. # and the cursor is here -------->   ^
  448. # @param $1 string  Characters out of $COMP_WORDBREAKS which should NOT be
  449. #     considered word breaks. This is useful for things like scp where
  450. #     we want to return host:path and not only path, so we would pass the
  451. #     colon (:) as $1 in this case.  Bash-3 doesn't do word splitting, so this
  452. #     ensures we get the same word on both bash-3 and bash-4.
  453. # @param $2 integer  Index number of word to return, negatively offset to the
  454. #     current word (default is 0, previous is 1), respecting the exclusions
  455. #     given at $1.  For example, `_get_cword "=:" 1' returns the word left of
  456. #     the current word, respecting the exclusions "=:".
  457. # @deprecated  Use `_get_comp_words_by_ref cur' instead
  458. # @see _get_comp_words_by_ref()
  459. _get_cword()
  460. {
  461.     local LC_CTYPE=C
  462.     local cword words
  463.     __reassemble_comp_words_by_ref "$1" words cword
  464.  
  465.     # return previous word offset by $2
  466.     if [[ ${2//[^0-9]/} ]]; then
  467.         printf "%s" "${words[cword-$2]}"
  468.     elif [[ "${#words[cword]}" -eq 0 || "$COMP_POINT" == "${#COMP_LINE}" ]]; then
  469.         printf "%s" "${words[cword]}"
  470.     else
  471.         local i
  472.         local cur="$COMP_LINE"
  473.         local index="$COMP_POINT"
  474.         for (( i = 0; i <= cword; ++i )); do
  475.             while [[
  476.                 # Current word fits in $cur?
  477.                 "${#cur}" -ge ${#words[i]} &&
  478.                 # $cur doesn't match cword?
  479.                 "${cur:0:${#words[i]}}" != "${words[i]}"
  480.             ]]; do
  481.                 # Strip first character
  482.                 cur="${cur:1}"
  483.                 # Decrease cursor position
  484.                 ((index--))
  485.             done
  486.  
  487.             # Does found word matches cword?
  488.             if [[ "$i" -lt "$cword" ]]; then
  489.                 # No, cword lies further;
  490.                 local old_size="${#cur}"
  491.                 cur="${cur#${words[i]}}"
  492.                 local new_size="${#cur}"
  493.                 index=$(( index - old_size + new_size ))
  494.             fi
  495.         done
  496.  
  497.         if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
  498.             # We messed up! At least return the whole word so things
  499.             # keep working
  500.             printf "%s" "${words[cword]}"
  501.         else
  502.             printf "%s" "${cur:0:$index}"
  503.         fi
  504.     fi
  505. } # _get_cword()
  506.  
  507.  
  508. # Get word previous to the current word.
  509. # This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4
  510. # will properly return the previous word with respect to any given exclusions to
  511. # COMP_WORDBREAKS.
  512. # @deprecated  Use `_get_comp_words_by_ref cur prev' instead
  513. # @see _get_comp_words_by_ref()
  514. #
  515. _get_pword()
  516. {
  517.     if [ $COMP_CWORD -ge 1 ]; then
  518.         _get_cword "${@:-}" 1;
  519.     fi
  520. }
  521.  
  522.  
  523. # If the word-to-complete contains a colon (:), left-trim COMPREPLY items with
  524. # word-to-complete.
  525. # On bash-3, and bash-4 with a colon in COMP_WORDBREAKS, words containing
  526. # colons are always completed as entire words if the word to complete contains
  527. # a colon.  This function fixes this, by removing the colon-containing-prefix
  528. # from COMPREPLY items.
  529. # The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in
  530. # your .bashrc:
  531. #
  532. #    # Remove colon (:) from list of word completion separators
  533. #    COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
  534. #
  535. # See also: Bash FAQ - E13) Why does filename completion misbehave if a colon
  536. # appears in the filename? - http://tiswww.case.edu/php/chet/bash/FAQ
  537. # @param $1 current word to complete (cur)
  538. # @modifies global array $COMPREPLY
  539. #
  540. __ltrim_colon_completions() {
  541.     # If word-to-complete contains a colon,
  542.     # and bash-version < 4,
  543.     # or bash-version >= 4 and COMP_WORDBREAKS contains a colon
  544.     if [[
  545.         "$1" == *:* && (
  546.             ${BASH_VERSINFO[0]} -lt 4 ||
  547.             (${BASH_VERSINFO[0]} -ge 4 && "$COMP_WORDBREAKS" == *:*)
  548.         )
  549.     ]]; then
  550.         # Remove colon-word prefix from COMPREPLY items
  551.         local colon_word=${1%${1##*:}}
  552.         local i=${#COMPREPLY[*]}
  553.         while [ $((--i)) -ge 0 ]; do
  554.             COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
  555.         done
  556.     fi
  557. } # __ltrim_colon_completions()
  558.  
  559.  
  560. # This function quotes the argument in a way so that readline dequoting
  561. # results in the original argument.  This is necessary for at least
  562. # `compgen' which requires its arguments quoted/escaped:
  563. #
  564. #     $ ls "a'b/"
  565. #     c
  566. #     $ compgen -f "a'b/"       # Wrong, doesn't return output
  567. #     $ compgen -f "a\'b/"      # Good (bash-4)
  568. #     a\'b/c
  569. #     $ compgen -f "a\\\\\'b/"  # Good (bash-3)
  570. #     a\'b/c
  571. #
  572. # On bash-3, special characters need to be escaped extra.  This is
  573. # unless the first character is a single quote (').  If the single
  574. # quote appears further down the string, bash default completion also
  575. # fails, e.g.:
  576. #
  577. #     $ ls 'a&b/'
  578. #     f
  579. #     $ foo 'a&b/<TAB>  # Becomes: foo 'a&b/f'
  580. #     $ foo a'&b/<TAB>  # Nothing happens
  581. #
  582. # See also:
  583. # - http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
  584. # - http://www.mail-archive.com/[email protected].\
  585. #   debian.org/msg01944.html
  586. # @param $1  Argument to quote
  587. # @param $2  Name of variable to return result to
  588. _quote_readline_by_ref()
  589. {
  590.     if [[ ${1:0:1} == "'" ]]; then
  591.         if [[ ${BASH_VERSINFO[0]} -ge 4 ]]; then
  592.             # Leave out first character
  593.             printf -v $2 %s "${1:1}"
  594.         else
  595.             # Quote word, leaving out first character
  596.             printf -v $2 %q "${1:1}"
  597.             # Double-quote word (bash-3)
  598.             printf -v $2 %q ${!2}
  599.         fi
  600.     elif [[ ${BASH_VERSINFO[0]} -le 3 && ${1:0:1} == '"' ]]; then
  601.         printf -v $2 %q "${1:1}"
  602.     else
  603.         printf -v $2 %q "$1"
  604.     fi
  605.  
  606.     # If result becomes quoted like this: $'string', re-evaluate in order to
  607.     # drop the additional quoting.  See also: http://www.mail-archive.com/
  608.     # [email protected]/msg01942.html
  609.     [[ ${!2:0:1} == '$' ]] && eval $2=${!2}
  610. } # _quote_readline_by_ref()
  611.  
  612.  
  613. # This function turns on "-o filenames" behavior dynamically. It is present
  614. # for bash < 4 reasons. See http://bugs.debian.org/272660#64 for info about
  615. # the bash < 4 compgen hack.
  616. _compopt_o_filenames()
  617. {
  618.     # We test for compopt availability first because directly invoking it on
  619.     # bash < 4 at this point may cause terminal echo to be turned off for some
  620.     # reason, see https://bugzilla.redhat.com/653669 for more info.
  621.     type compopt &>/dev/null && compopt -o filenames 2>/dev/null || \
  622.         compgen -f /non-existing-dir/ >/dev/null
  623. }
  624.  
  625.  
  626. # This function performs file and directory completion. It's better than
  627. # simply using 'compgen -f', because it honours spaces in filenames.
  628. # @param $1  If `-d', complete only on directories.  Otherwise filter/pick only
  629. #            completions with `.$1' and the uppercase version of it as file
  630. #            extension.
  631. #
  632. _filedir()
  633. {
  634.     local i IFS=$'\n' xspec
  635.  
  636.     _tilde "$cur" || return 0
  637.  
  638.     local -a toks
  639.     local quoted tmp
  640.  
  641.     _quote_readline_by_ref "$cur" quoted
  642.     toks=( ${toks[@]-} $(
  643.         compgen -d -- "$quoted" | {
  644.             while read -r tmp; do
  645.                 # TODO: I have removed a "[ -n $tmp ] &&" before 'printf ..',
  646.                 #       and everything works again. If this bug suddenly
  647.                 #       appears again (i.e. "cd /b<TAB>" becomes "cd /"),
  648.                 #       remember to check for other similar conditionals (here
  649.                 #       and _filedir_xspec()). --David
  650.                 printf '%s\n' $tmp
  651.             done
  652.         }
  653.     ))
  654.  
  655.     if [[ "$1" != -d ]]; then
  656.         # Munge xspec to contain uppercase version too
  657.         [[ ${BASH_VERSINFO[0]} -ge 4 ]] && \
  658.             xspec=${1:+"!*.@($1|${1^^})"} || \
  659.            xspec=${1:+"!*.@($1|$(printf %s $1 | tr '[:lower:]' '[:upper:]'))"}
  660.        toks=( ${toks[@]-} $( compgen -f -X "$xspec" -- $quoted) )
  661.    fi
  662.    [ ${#toks[@]} -ne 0 ] && _compopt_o_filenames
  663.  
  664.    # If the filter failed to produce anything, try w/o it (LP: #533985)
  665.    if [[ -n "$1" ]] && [[ "$1" != -d ]] && [[ ${#toks[@]} -lt 1 ]] ; then
  666.       toks=( ${toks[@]-} $( compgen -f -X -- $quoted) )
  667.    fi
  668.  
  669.    COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" )
  670. } # _filedir()
  671.  
  672.  
  673. # This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it
  674. # easier to support both "--foo bar" and "--foo=bar" style completions.
  675. # Returns 0 if current option was split, 1 otherwise.
  676. #
  677. _split_longopt()
  678. {
  679.    if [[ "$cur" == --?*=* ]]; then
  680.        # Cut also backslash before '=' in case it ended up there
  681.        # for some reason.
  682.        prev="${cur%%?(\\)=*}"
  683.        cur="${cur#*=}"
  684.        return 0
  685.    fi
  686.  
  687.    return 1
  688. }
  689.  
  690. # This function tries to parse the help output of the given command.
  691. # @param $1  command
  692. # @param $2  command options (default: --help)
  693. #
  694. _parse_help() {
  695.    $1 ${2:---help} 2>&1 | sed -e '/^[[:space:]]*-/!d' -e 's|[,/]| |g' | \
  696.        awk '{ print $1; if ($2 ~ /^-/) { print $2 } }' | sed -e 's|[<=].*||'
  697. }
  698.  
  699. # This function completes on signal names
  700. #
  701. _signals()
  702. {
  703.    local i
  704.  
  705.    # standard signal completion is rather braindead, so we need
  706.    # to hack around to get what we want here, which is to
  707.    # complete on a dash, followed by the signal name minus
  708.    # the SIG prefix
  709.    COMPREPLY=( $( compgen -A signal SIG${cur#-} ))
  710.    for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
  711.        COMPREPLY[i]=-${COMPREPLY[i]#SIG}
  712.    done
  713. }
  714.  
  715. # This function completes on known mac addresses
  716. #
  717. _mac_addresses()
  718. {
  719.    local re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}'
  720.    local PATH="$PATH:/sbin:/usr/sbin"
  721.  
  722.    # Local interfaces (Linux only?)
  723.    COMPREPLY=( "${COMPREPLY[@]}" $( ifconfig -a 2>/dev/null | sed -ne \
  724.        "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" ) )
  725.  
  726.    # ARP cache
  727.    COMPREPLY=( "${COMPREPLY[@]}" $( arp -an 2>/dev/null | sed -ne \
  728.        "s/.*[[:space:]]\($re\)[[:space:]].*/\1/p" -ne \
  729.        "s/.*[[:space:]]\($re\)[[:space:]]*$/\1/p" ) )
  730.  
  731.    # /etc/ethers
  732.    COMPREPLY=( "${COMPREPLY[@]}" $( sed -ne \
  733.        "s/^[[:space:]]*\($re\)[[:space:]].*/\1/p" /etc/ethers 2>/dev/null ) )
  734.  
  735.    COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) )
  736.    __ltrim_colon_completions "$cur"
  737. }
  738.  
  739. # This function completes on configured network interfaces
  740. #
  741. _configured_interfaces()
  742. {
  743.    if [ -f /etc/debian_version ]; then
  744.        # Debian system
  745.        COMPREPLY=( $( compgen -W "$( sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p'\
  746.            /etc/network/interfaces )" -- "$cur" ) )
  747.     elif [ -f /etc/SuSE-release ]; then
  748.         # SuSE system
  749.         COMPREPLY=( $( compgen -W "$( printf '%s\n' \
  750.            /etc/sysconfig/network/ifcfg-* | \
  751.            sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
  752.     elif [ -f /etc/pld-release ]; then
  753.         # PLD Linux
  754.         COMPREPLY=( $( compgen -W "$( command ls -B \
  755.            /etc/sysconfig/interfaces | \
  756.            sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
  757.     else
  758.         # Assume Red Hat
  759.         COMPREPLY=( $( compgen -W "$( printf '%s\n' \
  760.            /etc/sysconfig/network-scripts/ifcfg-* | \
  761.            sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
  762.     fi
  763. }
  764.  
  765. # This function completes on available kernels
  766. #
  767. _kernel_versions()
  768. {
  769.     COMPREPLY=( $( compgen -W '$( command ls /lib/modules )' -- "$cur" ) )
  770. }
  771.  
  772. # This function completes on all available network interfaces
  773. # -a: restrict to active interfaces only
  774. # -w: restrict to wireless interfaces only
  775. #
  776. _available_interfaces()
  777. {
  778.     local cmd
  779.  
  780.     if [ "${1:-}" = -w ]; then
  781.         cmd="iwconfig"
  782.     elif [ "${1:-}" = -a ]; then
  783.         cmd="ifconfig"
  784.     else
  785.         cmd="ifconfig -a"
  786.     fi
  787.  
  788.     COMPREPLY=( $( eval PATH="$PATH:/sbin" $cmd 2>/dev/null | \
  789.         awk '/^[^ \t]/ { print $1 }' ) )
  790.     COMPREPLY=( $( compgen -W '${COMPREPLY[@]/%[[:punct:]]/}' -- "$cur" ) )
  791. }
  792.  
  793.  
  794. # Perform tilde (~) completion
  795. # @return  True (0) if completion needs further processing,
  796. #          False (> 0) if tilde is followed by a valid username, completions
  797. #          are put in COMPREPLY and no further processing is necessary.
  798. _tilde() {
  799.     local result=0
  800.     # Does $1 start with tilde (~) and doesn't contain slash (/)?
  801.     if [[ ${1:0:1} == "~" && $1 == ${1//\/} ]]; then
  802.         _compopt_o_filenames
  803.         # Try generate username completions
  804.         COMPREPLY=( $( compgen -P '~' -u "${1#\~}" ) )
  805.         result=${#COMPREPLY[@]}
  806.     fi
  807.     return $result
  808. }
  809.  
  810.  
  811. # Expand variable starting with tilde (~)
  812. # We want to expand ~foo/... to /home/foo/... to avoid problems when
  813. # word-to-complete starting with a tilde is fed to commands and ending up
  814. # quoted instead of expanded.
  815. # Only the first portion of the variable from the tilde up to the first slash
  816. # (~../) is expanded.  The remainder of the variable, containing for example
  817. # a dollar sign variable ($) or asterisk (*) is not expanded.
  818. # Example usage:
  819. #
  820. #    $ v="~"; __expand_tilde_by_ref v; echo "$v"
  821. #
  822. # Example output:
  823. #
  824. #       v                  output
  825. #    --------         ----------------
  826. #    ~                /home/user
  827. #    ~foo/bar         /home/foo/bar
  828. #    ~foo/$HOME       /home/foo/$HOME
  829. #    ~foo/a  b        /home/foo/a  b
  830. #    ~foo/*           /home/foo/*
  831. #  
  832. # @param $1  Name of variable (not the value of the variable) to expand
  833. __expand_tilde_by_ref() {
  834.     # Does $1 start with tilde (~)?
  835.     if [ "${!1:0:1}" = "~" ]; then
  836.         # Does $1 contain slash (/)?
  837.         if [ "${!1}" != "${!1//\/}" ]; then
  838.             # Yes, $1 contains slash;
  839.             # 1: Remove * including and after first slash (/), i.e. "~a/b"
  840.             #    becomes "~a".  Double quotes allow eval.
  841.             # 2: Remove * before the first slash (/), i.e. "~a/b"
  842.             #    becomes "b".  Single quotes prevent eval.
  843.             #       +-----1----+ +---2----+
  844.             eval $1="${!1/%\/*}"/'${!1#*/}'
  845.         else
  846.             # No, $1 doesn't contain slash
  847.             eval $1="${!1}"
  848.         fi
  849.     fi
  850. } # __expand_tilde_by_ref()
  851.  
  852.  
  853. # This function expands tildes in pathnames
  854. #
  855. _expand()
  856. {
  857.     # FIXME: Why was this here?
  858.     #[ "$cur" != "${cur%\\}" ] && cur="$cur\\"
  859.  
  860.     # Expand ~username type directory specifications.  We want to expand
  861.     # ~foo/... to /home/foo/... to avoid problems when $cur starting with
  862.     # a tilde is fed to commands and ending up quoted instead of expanded.
  863.  
  864.     if [[ "$cur" == \~*/* ]]; then
  865.         eval cur=$cur
  866.     elif [[ "$cur" == \~* ]]; then
  867.         cur=${cur#\~}
  868.         COMPREPLY=( $( compgen -P '~' -u "$cur" ) )
  869.         [ ${#COMPREPLY[@]} -eq 1 ] && eval COMPREPLY[0]=${COMPREPLY[0]}
  870.         return ${#COMPREPLY[@]}
  871.     fi
  872. }
  873.  
  874. # This function completes on process IDs.
  875. # AIX and Solaris ps prefers X/Open syntax.
  876. [[ $UNAME == SunOS || $UNAME == AIX ]] &&
  877. _pids()
  878. {
  879.     COMPREPLY=( $( compgen -W '$( command ps -efo pid | sed 1d )' -- "$cur" ))
  880. } ||
  881. _pids()
  882. {
  883.     COMPREPLY=( $( compgen -W '$( command ps axo pid= )' -- "$cur" ) )
  884. }
  885.  
  886. # This function completes on process group IDs.
  887. # AIX and SunOS prefer X/Open, all else should be BSD.
  888. [[ $UNAME == SunOS || $UNAME == AIX ]] &&
  889. _pgids()
  890. {
  891.     COMPREPLY=( $( compgen -W '$( command ps -efo pgid | sed 1d )' -- "$cur" ))
  892. } ||
  893. _pgids()
  894. {
  895.     COMPREPLY=( $( compgen -W '$( command ps axo pgid= )' -- "$cur" ))
  896. }
  897.  
  898. # This function completes on process names.
  899. # AIX and SunOS prefer X/Open, all else should be BSD.
  900. [[ $UNAME == SunOS || $UNAME == AIX ]] &&
  901. _pnames()
  902. {
  903.     COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps -efo comm | \
  904.        sed -e 1d -e "s:.*/::" -e "s/^-//" | sort -u )' -- "$cur" ) )
  905. } ||
  906. _pnames()
  907. {
  908.     # FIXME: completes "[kblockd/0]" to "0". Previously it was completed
  909.     # to "kblockd" which isn't correct either. "kblockd/0" would be
  910.     # arguably most correct, but killall from psmisc 22 treats arguments
  911.     # containing "/" specially unless -r is given so that wouldn't quite
  912.     # work either. Perhaps it'd be best to not complete these to anything
  913.     # for now.
  914.     # Not using "ps axo comm" because under some Linux kernels, it
  915.     # truncates command names (see e.g. http://bugs.debian.org/497540#19)
  916.     COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps axo command= | \
  917.        sed -e "s/ .*//" -e "s:.*/::" -e "s/:$//" -e "s/^[[(-]//" \
  918.            -e "s/[])]$//" | sort -u )' -- "$cur" ) )
  919. }
  920.  
  921. # This function completes on user IDs
  922. #
  923. _uids()
  924. {
  925.     if type getent &>/dev/null; then
  926.         COMPREPLY=( $( compgen -W '$( getent passwd | cut -d: -f3 )' -- "$cur" ) )
  927.     elif type perl &>/dev/null; then
  928.         COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"' )' -- "$cur" ) )
  929.     else
  930.         # make do with /etc/passwd
  931.         COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/passwd )' -- "$cur" ) )
  932.     fi
  933. }
  934.  
  935. # This function completes on group IDs
  936. #
  937. _gids()
  938. {
  939.     if type getent &>/dev/null; then
  940.         COMPREPLY=( $( compgen -W '$( getent group | cut -d: -f3 )' \
  941.             -- "$cur" ) )
  942.     elif type perl &>/dev/null; then
  943.         COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"' )' -- "$cur" ) )
  944.     else
  945.         # make do with /etc/group
  946.         COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/group )' -- "$cur" ) )
  947.     fi
  948. }
  949.  
  950. # This function completes on services
  951. #
  952. _services()
  953. {
  954.     local sysvdir famdir
  955.     [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d || sysvdir=/etc/init.d
  956.     famdir=/etc/xinetd.d
  957.     COMPREPLY=( $( printf '%s\n' \
  958.         $sysvdir/!(*.rpm@(orig|new|save)|*~|functions) ) )
  959.  
  960.     if [ -d $famdir ]; then
  961.         COMPREPLY=( "${COMPREPLY[@]}" $( printf '%s\n' \
  962.             $famdir/!(*.rpm@(orig|new|save)|*~) ) )
  963.     fi
  964.  
  965.     COMPREPLY=( $( compgen -W '${COMPREPLY[@]#@($sysvdir|$famdir)/}' -- "$cur" ) )
  966. }
  967.  
  968. # This function completes on modules
  969. #
  970. _modules()
  971. {
  972.     local modpath
  973.     modpath=/lib/modules/$1
  974.     COMPREPLY=( $( compgen -W "$( command ls -R $modpath | \
  975.        sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.gz\)\{0,1\}$/\1/p' )" -- "$cur" ) )
  976. }
  977.  
  978. # This function completes on installed modules
  979. #
  980. _installed_modules()
  981. {
  982.     COMPREPLY=( $( compgen -W "$( PATH="$PATH:/sbin" lsmod | \
  983.        awk '{if (NR != 1) print $1}' )" -- "$1" ) )
  984. }
  985.  
  986. # This function completes on user or user:group format; as for chown and cpio.
  987. #
  988. # The : must be added manually; it will only complete usernames initially.
  989. # The legacy user.group format is not supported.
  990. #
  991. # @param $1  If -u, only return users/groups the user has access to in
  992. #            context of current completion.
  993. _usergroup()
  994. {
  995.     if [[ $cur = *\\\\* || $cur = *:*:* ]]; then
  996.         # Give up early on if something seems horribly wrong.
  997.         return
  998.     elif [[ $cur = *\\:* ]]; then
  999.         # Completing group after 'user\:gr<TAB>'.
  1000.         # Reply with a list of groups prefixed with 'user:', readline will
  1001.         # escape to the colon.
  1002.         local prefix
  1003.         prefix=${cur%%*([^:])}
  1004.         prefix=${prefix//\\}
  1005.         local mycur="${cur#*[:]}"
  1006.         if [[ $1 == -u ]]; then
  1007.             _allowed_groups "$mycur"
  1008.         else
  1009.             local IFS=$'\n'
  1010.             COMPREPLY=( $( compgen -g -- "$mycur" ) )
  1011.         fi
  1012.         COMPREPLY=( $( compgen -P "$prefix" -W "${COMPREPLY[@]}" ) )
  1013.     elif [[ $cur = *:* ]]; then
  1014.         # Completing group after 'user:gr<TAB>'.
  1015.         # Reply with a list of unprefixed groups since readline with split on :
  1016.         # and only replace the 'gr' part
  1017.         local mycur="${cur#*:}"
  1018.         if [[ $1 == -u ]]; then
  1019.             _allowed_groups "$mycur"
  1020.         else
  1021.             local IFS=$'\n'
  1022.             COMPREPLY=( $( compgen -g -- "$mycur" ) )
  1023.         fi
  1024.     else
  1025.         # Completing a partial 'usernam<TAB>'.
  1026.         #
  1027.         # Don't suffix with a : because readline will escape it and add a
  1028.         # slash. It's better to complete into 'chown username ' than 'chown
  1029.         # username\:'.
  1030.         if [[ $1 == -u ]]; then
  1031.             _allowed_users "$cur"
  1032.         else
  1033.             local IFS=$'\n'
  1034.             COMPREPLY=( $( compgen -u -- "$cur" ) )
  1035.         fi
  1036.     fi
  1037. }
  1038.  
  1039. _allowed_users()
  1040. {
  1041.     if _complete_as_root; then
  1042.         local IFS=$'\n'
  1043.         COMPREPLY=( $( compgen -u -- "${1:-$cur}" ) )
  1044.     else
  1045.         local IFS=$'\n '
  1046.         COMPREPLY=( $( compgen -W \
  1047.             "$( id -un 2>/dev/null || whoami 2>/dev/null )" -- "${1:-$cur}" ) )
  1048.     fi
  1049. }
  1050.  
  1051. _allowed_groups()
  1052. {
  1053.     if _complete_as_root; then
  1054.         local IFS=$'\n'
  1055.         COMPREPLY=( $( compgen -g -- "$1" ) )
  1056.     else
  1057.         local IFS=$'\n '
  1058.         COMPREPLY=( $( compgen -W \
  1059.             "$( id -Gn 2>/dev/null || groups 2>/dev/null )" -- "$1" ) )
  1060.     fi
  1061. }
  1062.  
  1063. # This function completes on valid shells
  1064. #
  1065. _shells()
  1066. {
  1067.     COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W \
  1068.         '$( command grep "^[[:space:]]*/" /etc/shells 2>/dev/null )' \
  1069.         -- "$cur" ) )
  1070. }
  1071.  
  1072. # This function completes on valid filesystem types
  1073. #
  1074. _fstypes()
  1075. {
  1076.     local fss
  1077.  
  1078.     if [ -e /proc/filesystems ] ; then
  1079.         # Linux
  1080.         fss="$( cut -d$'\t' -f2 /proc/filesystems )
  1081.             $( awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null )"
  1082.     else
  1083.         # Generic
  1084.         fss="$( awk '/^[ \t]*[^#]/ { print $3 }' /etc/fstab 2>/dev/null )
  1085.             $( awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null )
  1086.             $( awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null )
  1087.             $( awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null )
  1088.             $( [ -d /etc/fs ] && command ls /etc/fs )"
  1089.     fi
  1090.  
  1091.     [ -n "$fss" ] && \
  1092.         COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$fss" -- "$cur" ) )
  1093. }
  1094.  
  1095. # Get real command.
  1096. # - arg: $1  Command
  1097. # - stdout:  Filename of command in PATH with possible symbolic links resolved.
  1098. #            Empty string if command not found.
  1099. # - return:  True (0) if command found, False (> 0) if not.
  1100. _realcommand()
  1101. {
  1102.     type -P "$1" > /dev/null && {
  1103.         if type -p realpath > /dev/null; then
  1104.             realpath "$(type -P "$1")"
  1105.         elif type -p readlink > /dev/null; then
  1106.             readlink -f "$(type -P "$1")"
  1107.         else
  1108.             type -P "$1"
  1109.         fi
  1110.     }
  1111. }
  1112.  
  1113. # This function returns the first arugment, excluding options
  1114. # @param $1 chars  Characters out of $COMP_WORDBREAKS which should
  1115. #     NOT be considered word breaks. See __reassemble_comp_words_by_ref.
  1116. _get_first_arg()
  1117. {
  1118.     local i
  1119.  
  1120.     arg=
  1121.     for (( i=1; i < COMP_CWORD; i++ )); do
  1122.         if [[ "${COMP_WORDS[i]}" != -* ]]; then
  1123.             arg=${COMP_WORDS[i]}
  1124.             break
  1125.         fi
  1126.     done
  1127. }
  1128.  
  1129.  
  1130. # This function counts the number of args, excluding options
  1131. # @param $1 chars  Characters out of $COMP_WORDBREAKS which should
  1132. #     NOT be considered word breaks. See __reassemble_comp_words_by_ref.
  1133. _count_args()
  1134. {
  1135.     local i cword words
  1136.     __reassemble_comp_words_by_ref "$1" words cword
  1137.  
  1138.     args=1
  1139.     for i in "${words[@]:1:cword-1}"; do
  1140.         [[ "$i" != -* ]] && args=$(($args+1))
  1141.     done
  1142. }
  1143.  
  1144. # This function completes on PCI IDs
  1145. #
  1146. _pci_ids()
  1147. {
  1148.     COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
  1149.         "$( PATH="$PATH:/sbin" lspci -n | awk '{print $3}')" -- "$cur" ) )
  1150. }
  1151.  
  1152. # This function completes on USB IDs
  1153. #
  1154. _usb_ids()
  1155. {
  1156.     COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
  1157.         "$( PATH="$PATH:/sbin" lsusb | awk '{print $6}' )" -- "$cur" ) )
  1158. }
  1159.  
  1160. # CD device names
  1161. _cd_devices()
  1162. {
  1163.     COMPREPLY=( "${COMPREPLY[@]}"
  1164.         $( compgen -f -d -X "!*/?([amrs])cd*" -- "${cur:-/dev/}" ) )
  1165. }
  1166.  
  1167. # DVD device names
  1168. _dvd_devices()
  1169. {
  1170.     COMPREPLY=( "${COMPREPLY[@]}"
  1171.         $( compgen -f -d -X "!*/?(r)dvd*" -- "${cur:-/dev/}" ) )
  1172. }
  1173.  
  1174. # start of section containing completion functions for external programs
  1175.  
  1176. # a little help for FreeBSD ports users
  1177. [ $UNAME = FreeBSD ] && complete -W 'index search fetch fetch-list extract \
  1178.    patch configure build install reinstall deinstall clean clean-depends \
  1179.    kernel buildworld' make
  1180.  
  1181. # This function provides simple user@host completion
  1182. #
  1183. _user_at_host() {
  1184.     local cur
  1185.  
  1186.     COMPREPLY=()
  1187.     _get_comp_words_by_ref -n : cur
  1188.  
  1189.     if [[ $cur == *@* ]]; then
  1190.         _known_hosts_real "$cur"
  1191.     else
  1192.         COMPREPLY=( $( compgen -u -- "$cur" ) )
  1193.     fi
  1194.  
  1195.     return 0
  1196. }
  1197. shopt -u hostcomplete && complete -F _user_at_host -o nospace talk ytalk finger
  1198.  
  1199. # NOTE: Using this function as a helper function is deprecated.  Use
  1200. #       `_known_hosts_real' instead.
  1201. _known_hosts()
  1202. {
  1203.     local options
  1204.     COMPREPLY=()
  1205.  
  1206.     # NOTE: Using `_known_hosts' as a helper function and passing options
  1207.     #       to `_known_hosts' is deprecated: Use `_known_hosts_real' instead.
  1208.     [[ "$1" == -a || "$2" == -a ]] && options=-a
  1209.     [[ "$1" == -c || "$2" == -c ]] && options="$options -c"
  1210.     _known_hosts_real $options "$(_get_cword :)"
  1211. } # _known_hosts()
  1212.  
  1213. # Helper function for completing _known_hosts.
  1214. # This function performs host completion based on ssh's config and known_hosts
  1215. # files, as well as hostnames reported by avahi-browse if
  1216. # COMP_KNOWN_HOSTS_WITH_AVAHI is set to a non-empty value.  Also hosts from
  1217. # HOSTFILE (compgen -A hostname) are added, unless
  1218. # COMP_KNOWN_HOSTS_WITH_HOSTFILE is set to an empty value.
  1219. # Usage: _known_hosts_real [OPTIONS] CWORD
  1220. # Options:  -a             Use aliases
  1221. #           -c             Use `:' suffix
  1222. #           -F configfile  Use `configfile' for configuration settings
  1223. #           -p PREFIX      Use PREFIX
  1224. # Return: Completions, starting with CWORD, are added to COMPREPLY[]
  1225. _known_hosts_real()
  1226. {
  1227.     local configfile flag prefix
  1228.     local cur curd awkcur user suffix aliases i host
  1229.     local -a kh khd config
  1230.  
  1231.     local OPTIND=1
  1232.     while getopts "acF:p:" flag "$@"; do
  1233.         case $flag in
  1234.             a) aliases='yes' ;;
  1235.             c) suffix=':' ;;
  1236.             F) configfile=$OPTARG ;;
  1237.             p) prefix=$OPTARG ;;
  1238.         esac
  1239.     done
  1240.     [ $# -lt $OPTIND ] && echo "error: $FUNCNAME: missing mandatory argument CWORD"
  1241.     cur=${!OPTIND}; let "OPTIND += 1"
  1242.     [ $# -ge $OPTIND ] && echo "error: $FUNCNAME("$@"): unprocessed arguments:"\
  1243.     $(while [ $# -ge $OPTIND ]; do printf '%s\n' ${!OPTIND}; shift; done)
  1244.  
  1245.     [[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
  1246.     kh=()
  1247.  
  1248.     # ssh config files
  1249.     if [ -n "$configfile" ]; then
  1250.         [ -r "$configfile" ] &&
  1251.         config=( "${config[@]}" "$configfile" )
  1252.     else
  1253.         for i in /etc/ssh/ssh_config "${HOME}/.ssh/config" \
  1254.             "${HOME}/.ssh2/config"; do
  1255.             [ -r $i ] && config=( "${config[@]}" "$i" )
  1256.         done
  1257.     fi
  1258.  
  1259.     # Known hosts files from configs
  1260.     if [ ${#config[@]} -gt 0 ]; then
  1261.         local OIFS=$IFS IFS=$'\n'
  1262.         local -a tmpkh
  1263.         # expand paths (if present) to global and user known hosts files
  1264.         # TODO(?): try to make known hosts files with more than one consecutive
  1265.         #          spaces in their name work (watch out for ~ expansion
  1266.         #          breakage! Alioth#311595)
  1267.         tmpkh=( $( awk 'sub("^[ \t]*([Gg][Ll][Oo][Bb][Aa][Ll]|[Uu][Ss][Ee][Rr])[Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee][ \t]+", "") { print $0 }' "${config[@]}" | sort -u ) )
  1268.         for i in "${tmpkh[@]}"; do
  1269.             # Remove possible quotes
  1270.             i=${i//\"}
  1271.             # Eval/expand possible `~' or `~user'
  1272.             __expand_tilde_by_ref i
  1273.             [ -r "$i" ] && kh=( "${kh[@]}" "$i" )
  1274.         done
  1275.         IFS=$OIFS
  1276.     fi
  1277.  
  1278.     if [ -z "$configfile" ]; then
  1279.         # Global and user known_hosts files
  1280.         for i in /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2 \
  1281.             /etc/known_hosts /etc/known_hosts2 ~/.ssh/known_hosts \
  1282.             ~/.ssh/known_hosts2; do
  1283.             [ -r $i ] && kh=( "${kh[@]}" $i )
  1284.         done
  1285.         for i in /etc/ssh2/knownhosts ~/.ssh2/hostkeys; do
  1286.             [ -d $i ] && khd=( "${khd[@]}" $i/*pub )
  1287.         done
  1288.     fi
  1289.  
  1290.     # If we have known_hosts files to use
  1291.     if [[ ${#kh[@]} -gt 0 || ${#khd[@]} -gt 0 ]]; then
  1292.         # Escape slashes and dots in paths for awk
  1293.         awkcur=${cur//\//\\\/}
  1294.         awkcur=${awkcur//\./\\\.}
  1295.         curd=$awkcur
  1296.  
  1297.         if [[ "$awkcur" == [0-9]*[.:]* ]]; then
  1298.             # Digits followed by a dot or a colon - just search for that
  1299.             awkcur="^$awkcur[.:]*"
  1300.         elif [[ "$awkcur" == [0-9]* ]]; then
  1301.             # Digits followed by no dot or colon - search for digits followed
  1302.             # by a dot or a colon
  1303.             awkcur="^$awkcur.*[.:]"
  1304.         elif [ -z "$awkcur" ]; then
  1305.             # A blank - search for a dot, a colon, or an alpha character
  1306.             awkcur="[a-z.:]"
  1307.         else
  1308.             awkcur="^$awkcur"
  1309.         fi
  1310.  
  1311.         if [ ${#kh[@]} -gt 0 ]; then
  1312.             # FS needs to look for a comma separated list
  1313.             COMPREPLY=( "${COMPREPLY[@]}" $( awk 'BEGIN {FS=","}
  1314.            /^\s*[^|\#]/ {for (i=1; i<=2; ++i) { \
  1315.            sub(" .*$", "", $i); \
  1316.            sub("^\\[", "", $i); sub("\\](:[0-9]+)?$", "", $i); \
  1317.            if ($i ~ /'"$awkcur"'/) {print $i} \
  1318.            }}' "${kh[@]}" 2>/dev/null ) )
  1319.         fi
  1320.         if [ ${#khd[@]} -gt 0 ]; then
  1321.             # Needs to look for files called
  1322.             # .../.ssh2/key_22_<hostname>.pub
  1323.             # dont fork any processes, because in a cluster environment,
  1324.             # there can be hundreds of hostkeys
  1325.             for i in "${khd[@]}" ; do
  1326.                 if [[ "$i" == *key_22_$curd*.pub && -r "$i" ]]; then
  1327.                     host=${i/#*key_22_/}
  1328.                     host=${host/%.pub/}
  1329.                     COMPREPLY=( "${COMPREPLY[@]}" $host )
  1330.                 fi
  1331.             done
  1332.         fi
  1333.  
  1334.         # apply suffix and prefix
  1335.         for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
  1336.             COMPREPLY[i]=$prefix$user${COMPREPLY[i]}$suffix
  1337.         done
  1338.     fi
  1339.  
  1340.     # append any available aliases from config files
  1341.     if [[ ${#config[@]} -gt 0 && -n "$aliases" ]]; then
  1342.         local hosts=$( sed -ne 's/^[ \t]*[Hh][Oo][Ss][Tt]\([Nn][Aa][Mm][Ee]\)\{0,1\}['"$'\t '"']\{1,\}\([^#*?]*\)\(#.*\)\{0,1\}$/\2/p' "${config[@]}" )
  1343.         COMPREPLY=( "${COMPREPLY[@]}" $( compgen  -P "$prefix$user" \
  1344.             -S "$suffix" -W "$hosts" -- "$cur" ) )
  1345.     fi
  1346.  
  1347.     # Add hosts reported by avahi-browse, if desired and it's available.
  1348.  
  1349.     # This feature is disabled because it does not scale to
  1350.     #  larger networks. See:
  1351.     # https://bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/510591
  1352.  
  1353.     #if [[ ${COMP_KNOWN_HOSTS_WITH_AVAHI:-} ]] && \
  1354.     #    type avahi-browse &>/dev/null; then
  1355.         # The original call to avahi-browse also had "-k", to avoid lookups
  1356.         # into avahi's services DB. We don't need the name of the service, and
  1357.         # if it contains ";", it may mistify the result. But on Gentoo (at
  1358.         # least), -k wasn't available (even if mentioned in the manpage) some
  1359.         # time ago, so...
  1360.     #    COMPREPLY=( "${COMPREPLY[@]}" $( \
  1361.     #        compgen -P "$prefix$user" -S "$suffix" -W \
  1362.     #        "$( avahi-browse -cpr _workstation._tcp 2>/dev/null | \
  1363.     #             awk -F';' '/^=/ { print $7 }' | sort -u )" -- "$cur" ) )
  1364.     #fi
  1365.  
  1366.     # Add results of normal hostname completion, unless
  1367.     # `COMP_KNOWN_HOSTS_WITH_HOSTFILE' is set to an empty value.
  1368.     if [ -n "${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1}" ]; then
  1369.         COMPREPLY=( "${COMPREPLY[@]}"
  1370.             $( compgen -A hostname -P "$prefix$user" -S "$suffix" -- "$cur" ) )
  1371.     fi
  1372.  
  1373.     __ltrim_colon_completions "$prefix$user$cur"
  1374.  
  1375.     return 0
  1376. } # _known_hosts_real()
  1377. complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 ping \
  1378.     ping6 fping fping6 telnet host nslookup rsh rlogin ftp dig mtr \
  1379.     ssh-installkeys showmount
  1380.  
  1381. # This meta-cd function observes the CDPATH variable, so that cd additionally
  1382. # completes on directories under those specified in CDPATH.
  1383. #
  1384. _cd()
  1385. {
  1386.     local cur IFS=$'\n' i j k
  1387.     _get_comp_words_by_ref cur
  1388.  
  1389.     # try to allow variable completion
  1390.     if [[ "$cur" == ?(\\)\$* ]]; then
  1391.         COMPREPLY=( $( compgen -v -P '$' -- "${cur#?(\\)$}" ) )
  1392.         return 0
  1393.     fi
  1394.  
  1395.     _compopt_o_filenames
  1396.  
  1397.     # Use standard dir completion if no CDPATH or parameter starts with /,
  1398.     # ./ or ../
  1399.     if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
  1400.         _filedir -d
  1401.         return 0
  1402.     fi
  1403.  
  1404.     local -r mark_dirs=$(_rl_enabled mark-directories && echo y)
  1405.     local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y)
  1406.  
  1407.     # we have a CDPATH, so loop on its contents
  1408.     for i in ${CDPATH//:/$'\n'}; do
  1409.         # create an array of matched subdirs
  1410.         k="${#COMPREPLY[@]}"
  1411.         for j in $( compgen -d $i/$cur ); do
  1412.             if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
  1413.                 j="${j}/"
  1414.             fi
  1415.             COMPREPLY[k++]=${j#$i/}
  1416.         done
  1417.     done
  1418.  
  1419.     _filedir -d
  1420.  
  1421.     if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
  1422.         i=${COMPREPLY[0]}
  1423.         if [[ "$i" == "$cur" && $i != "*/" ]]; then
  1424.             COMPREPLY[0]="${i}/"
  1425.         fi
  1426.     fi
  1427.  
  1428.     return 0
  1429. }
  1430. if shopt -q cdable_vars; then
  1431.     complete -v -F _cd -o nospace cd
  1432. else
  1433.     complete -F _cd -o nospace cd
  1434. fi
  1435.  
  1436. # a wrapper method for the next one, when the offset is unknown
  1437. _command()
  1438. {
  1439.     local offset i
  1440.  
  1441.     # find actual offset, as position of the first non-option
  1442.     offset=1
  1443.     for (( i=1; i <= COMP_CWORD; i++ )); do
  1444.         if [[ "${COMP_WORDS[i]}" != -* ]]; then
  1445.             offset=$i
  1446.             break
  1447.         fi
  1448.     done
  1449.     _command_offset $offset
  1450. }
  1451.  
  1452. # A meta-command completion function for commands like sudo(8), which need to
  1453. # first complete on a command, then complete according to that command's own
  1454. # completion definition - currently not quite foolproof (e.g. mount and umount
  1455. # don't work properly), but still quite useful.
  1456. #
  1457. _command_offset()
  1458. {
  1459.     local cur func cline cspec noglob cmd i char_offset word_offset \
  1460.         _COMMAND_FUNC _COMMAND_FUNC_ARGS
  1461.  
  1462.     word_offset=$1
  1463.  
  1464.     # rewrite current completion context before invoking
  1465.     # actual command completion
  1466.  
  1467.     # find new first word position, then
  1468.     # rewrite COMP_LINE and adjust COMP_POINT
  1469.     local first_word=${COMP_WORDS[$word_offset]}
  1470.     for (( i=0; i <= ${#COMP_LINE}; i++ )); do
  1471.         if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
  1472.             char_offset=$i
  1473.             break
  1474.         fi
  1475.     done
  1476.     COMP_LINE=${COMP_LINE:$char_offset}
  1477.     COMP_POINT=$(( COMP_POINT - $char_offset ))
  1478.  
  1479.     # shift COMP_WORDS elements and adjust COMP_CWORD
  1480.     for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
  1481.         COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
  1482.     done
  1483.     for (( i; i <= COMP_CWORD; i++ )); do
  1484.         unset COMP_WORDS[i];
  1485.     done
  1486.     COMP_CWORD=$(( $COMP_CWORD - $word_offset ))
  1487.  
  1488.     COMPREPLY=()
  1489.     _get_comp_words_by_ref cur
  1490.  
  1491.     if [[ $COMP_CWORD -eq 0 ]]; then
  1492.         _compopt_o_filenames
  1493.         COMPREPLY=( $( compgen -c -- "$cur" ) )
  1494.     else
  1495.         cmd=${COMP_WORDS[0]}
  1496.         if complete -p ${cmd##*/} &>/dev/null; then
  1497.             cspec=$( complete -p ${cmd##*/} )
  1498.             if [ "${cspec#* -F }" != "$cspec" ]; then
  1499.                 # complete -F <function>
  1500.  
  1501.                 # get function name
  1502.                 func=${cspec#*-F }
  1503.                 func=${func%% *}
  1504.  
  1505.                 if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
  1506.                     $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
  1507.                 else
  1508.                     $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
  1509.                 fi
  1510.  
  1511.                 # remove any \: generated by a command that doesn't
  1512.                 # default to filenames or dirnames (e.g. sudo chown)
  1513.                 # FIXME: I'm pretty sure this does not work!
  1514.                 if [ "${cspec#*-o }" != "$cspec" ]; then
  1515.                     cspec=${cspec#*-o }
  1516.                     cspec=${cspec%% *}
  1517.                     if [[ "$cspec" != @(dir|file)names ]]; then
  1518.                         COMPREPLY=("${COMPREPLY[@]//\\\\:/:}")
  1519.                     else
  1520.                         _compopt_o_filenames
  1521.                     fi
  1522.                 fi
  1523.             elif [ -n "$cspec" ]; then
  1524.                 cspec=${cspec#complete};
  1525.                 cspec=${cspec%%${cmd##*/}};
  1526.                 COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
  1527.             fi
  1528.         elif [ ${#COMPREPLY[@]} -eq 0 ]; then
  1529.             _filedir
  1530.         fi
  1531.     fi
  1532. }
  1533. complete -F _command aoss command do else eval exec ltrace nice nohup padsp \
  1534.     then time tsocks vsound xargs
  1535.  
  1536. _root_command()
  1537. {
  1538.     local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
  1539.     local root_command=$1
  1540.     _command $1 $2 $3
  1541. }
  1542. complete -F _root_command fakeroot gksu gksudo kdesudo really sudo
  1543.  
  1544. # Return true if the completion should be treated as running as root
  1545. _complete_as_root()
  1546. {
  1547.     [[ $EUID -eq 0 || ${root_command:-} ]]
  1548. }
  1549.  
  1550. _longopt()
  1551. {
  1552.     local cur prev split=false
  1553.     _get_comp_words_by_ref -n = cur prev
  1554.  
  1555.     _split_longopt && split=true
  1556.  
  1557.     case "$prev" in
  1558.         --*[Dd][Ii][Rr]*)
  1559.             _filedir -d
  1560.             return 0
  1561.             ;;
  1562.         --*[Ff][Ii][Ll][Ee]*|--*[Pp][Aa][Tt][Hh]*)
  1563.             _filedir
  1564.             return 0
  1565.             ;;
  1566.     esac
  1567.  
  1568.     $split && return 0
  1569.  
  1570.     if [[ "$cur" == -* ]]; then
  1571.         COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | \
  1572.            sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}\).*/\1/p' | sort -u )" \
  1573.             -- "$cur" ) )
  1574.     elif [[ "$1" == @(mk|rm)dir ]]; then
  1575.         _filedir -d
  1576.     else
  1577.         _filedir
  1578.     fi
  1579. }
  1580. # makeinfo and texi2dvi are defined elsewhere.
  1581. for i in a2ps awk bash bc bison cat colordiff cp csplit \
  1582.     curl cut date df diff dir du enscript env expand fmt fold gperf gprof \
  1583.     grep grub head indent irb ld ldd less ln ls m4 md5sum mkdir mkfifo mknod \
  1584.     mv netstat nl nm objcopy objdump od paste patch pr ptx readelf rm rmdir \
  1585.     sed seq sha{,1,224,256,384,512}sum shar sort split strip tac tail tee \
  1586.     texindex touch tr uname unexpand uniq units vdir wc wget who; do
  1587.     have $i && complete -F _longopt -o default $i
  1588. done
  1589. unset i
  1590.  
  1591. _filedir_xspec()
  1592. {
  1593.     local IFS cur xspec
  1594.  
  1595.     IFS=$'\n'
  1596.     COMPREPLY=()
  1597.     _get_comp_words_by_ref cur
  1598.  
  1599.     _expand || return 0
  1600.  
  1601.     # get first exclusion compspec that matches this command
  1602.     xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \$0; exit }" \
  1603.         "$BASH_COMPLETION" )
  1604.     # prune to leave nothing but the -X spec
  1605.     xspec=${xspec#*-X }
  1606.     xspec=${xspec%% *}
  1607.  
  1608.     local -a toks
  1609.     local tmp
  1610.  
  1611.     toks=( ${toks[@]-} $(
  1612.         compgen -d -- "$(quote_readline "$cur")" | {
  1613.         while read -r tmp; do
  1614.             # see long TODO comment in _filedir() --David
  1615.             printf '%s\n' $tmp
  1616.         done
  1617.         }
  1618.         ))
  1619.  
  1620.     # Munge xspec to contain uppercase version too
  1621.     eval xspec="${xspec}"
  1622.     local matchop=!
  1623.     if [[ $xspec == !* ]]; then
  1624.         xspec=${xspec#!}
  1625.         matchop=@
  1626.     fi
  1627.     [[ ${BASH_VERSINFO[0]} -ge 4 ]] && \
  1628.         xspec="$matchop($xspec|${xspec^^})" || \
  1629.         xspec="$matchop($xspec|$(printf %s $xspec | tr '[:lower:]' '[:upper:]'))"
  1630.  
  1631.     toks=( ${toks[@]-} $(
  1632.         eval compgen -f -X "!$xspec" -- "\$(quote_readline "\$cur")" | {
  1633.         while read -r tmp; do
  1634.             [ -n $tmp ] && printf '%s\n' $tmp
  1635.         done
  1636.         }
  1637.         ))
  1638.  
  1639.     [ ${#toks[@]} -ne 0 ] && _compopt_o_filenames
  1640.     COMPREPLY=( "${toks[@]}" )
  1641. }
  1642. list=( $( sed -ne '/^# START exclude/,/^# FINISH exclude/p' "$BASH_COMPLETION" | \
  1643.     # read exclusion compspecs
  1644.     (
  1645.     while read line
  1646.     do
  1647.         # ignore compspecs that are commented out
  1648.         if [ "${line#\#}" != "$line" ]; then continue; fi
  1649.         line=${line%# START exclude*}
  1650.         line=${line%# FINISH exclude*}
  1651.         line=${line##*\'}
  1652.         list=( "${list[@]}" $line )
  1653.     done
  1654.     printf '%s ' "${list[@]}"
  1655.     )
  1656.     ) )
  1657. # remove previous compspecs
  1658. if [ ${#list[@]} -gt 0 ]; then
  1659.     eval complete -r ${list[@]}
  1660.     # install new compspecs
  1661.     eval complete -F _filedir_xspec "${list[@]}"
  1662. fi
  1663. unset list
  1664.  
  1665. # source completion directory definitions
  1666. if [[ -d $BASH_COMPLETION_COMPAT_DIR && -r $BASH_COMPLETION_COMPAT_DIR && \
  1667.     -x $BASH_COMPLETION_COMPAT_DIR ]]; then
  1668.     for i in $(LC_ALL=C command ls "$BASH_COMPLETION_COMPAT_DIR"); do
  1669.         i=$BASH_COMPLETION_COMPAT_DIR/$i
  1670.         [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)|Makefile*) \
  1671.             && -f $i && -r $i ]] && . "$i"
  1672.     done
  1673. fi
  1674. if [[ $BASH_COMPLETION_DIR != $BASH_COMPLETION_COMPAT_DIR && \
  1675.     -d $BASH_COMPLETION_DIR && -r $BASH_COMPLETION_DIR && \
  1676.     -x $BASH_COMPLETION_DIR ]]; then
  1677.     for i in $(LC_ALL=C command ls "$BASH_COMPLETION_DIR"); do
  1678.         i=$BASH_COMPLETION_DIR/$i
  1679.         [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)|Makefile*) \
  1680.             && -f $i && -r $i ]] && . "$i"
  1681.     done
  1682. fi
  1683. unset i
  1684.  
  1685. # source user completion file
  1686. [[ $BASH_COMPLETION != ~/.bash_completion && -r ~/.bash_completion ]] \
  1687.     && . ~/.bash_completion
  1688. unset -f have
  1689. unset UNAME USERLAND have
  1690.  
  1691. set $BASH_COMPLETION_ORIGINAL_V_VALUE
  1692. unset BASH_COMPLETION_ORIGINAL_V_VALUE
  1693.  
  1694. # Local variables:
  1695. # mode: shell-script
  1696. # sh-basic-offset: 4
  1697. # sh-indent-comment: t
  1698. # indent-tabs-mode: nil
  1699. # End:
  1700. # ex: ts=4 sw=4 et filetype=sh
Advertisement
Add Comment
Please, Sign In to add comment