PageRenderTime 179ms CodeModel.GetById 128ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/bash_completion

http://github.com/brinkman83/bashrc
#! | 1669 lines | 1461 code | 208 blank | 0 comment | 0 complexity | eed64bd1d0c33d5a550af9faacc439c4 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1#
   2#   bash_completion - programmable completion functions for bash 3.x
   3#             (backwards compatible with bash 2.05b)
   4#
   5#   Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
   6#             © 2009, Bash Completion Maintainers
   7#                     <bash-completion-devel@lists.alioth.debian.org>
   8#
   9#   This program is free software; you can redistribute it and/or modify
  10#   it under the terms of the GNU General Public License as published by
  11#   the Free Software Foundation; either version 2, or (at your option)
  12#   any later version.
  13#
  14#   This program is distributed in the hope that it will be useful,
  15#   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17#   GNU General Public License for more details.
  18#
  19#   You should have received a copy of the GNU General Public License
  20#   along with this program; if not, write to the Free Software Foundation,
  21#   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22#
  23#   The latest version of this software can be obtained here:
  24#
  25#   http://bash-completion.alioth.debian.org/
  26#
  27#   RELEASE: 1.1
  28
  29if [[ $- == *v* ]]; then
  30    BASH_COMPLETION_ORIGINAL_V_VALUE="-v"
  31else
  32    BASH_COMPLETION_ORIGINAL_V_VALUE="+v"
  33fi
  34
  35if [[ -n $BASH_COMPLETION_DEBUG ]]; then
  36    set -v
  37else
  38    set +v
  39fi
  40
  41# Alter the following to reflect the location of this file.
  42#
  43[ -n "$BASH_COMPLETION" ] || BASH_COMPLETION=/etc/bash_completion
  44[ -n "$BASH_COMPLETION_DIR" ] || BASH_COMPLETION_DIR=/etc/bash_completion.d
  45[ -n "$BASH_COMPLETION_COMPAT_DIR" ] || BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
  46readonly BASH_COMPLETION BASH_COMPLETION_DIR BASH_COMPLETION_COMPAT_DIR
  47
  48# Set a couple of useful vars
  49#
  50UNAME=$( uname -s )
  51# strip OS type and version under Cygwin (e.g. CYGWIN_NT-5.1 => Cygwin)
  52UNAME=${UNAME/CYGWIN_*/Cygwin}
  53
  54case ${UNAME} in
  55    Linux|GNU|GNU/*) USERLAND=GNU ;;
  56    *) USERLAND=${UNAME} ;;
  57esac
  58
  59# features supported by bash 2.05 and higher
  60if [ ${BASH_VERSINFO[0]} -eq 2 ] && [[ ${BASH_VERSINFO[1]} > 04 ]] ||
  61    [ ${BASH_VERSINFO[0]} -gt 2 ]; then
  62    declare -r bash205=$BASH_VERSION 2>/dev/null || :
  63    default="-o default"
  64    dirnames="-o dirnames"
  65    filenames="-o filenames"
  66    compopt=:
  67fi
  68# features supported by bash 2.05b and higher
  69if [ ${BASH_VERSINFO[0]} -eq 2 ] && [[ ${BASH_VERSINFO[1]} = "05b" ]] ||
  70    [ ${BASH_VERSINFO[0]} -gt 2 ]; then
  71    declare -r bash205b=$BASH_VERSION 2>/dev/null || :
  72    nospace="-o nospace"
  73fi
  74# features supported by bash 3.0 and higher
  75if [ ${BASH_VERSINFO[0]} -gt 2 ]; then
  76    declare -r bash3=$BASH_VERSION 2>/dev/null || :
  77    bashdefault="-o bashdefault"
  78    plusdirs="-o plusdirs"
  79fi
  80# features supported by bash 4.0 and higher
  81if [ ${BASH_VERSINFO[0]} -gt 3 ]; then
  82    declare -r bash4=$BASH_VERSION 2>/dev/null || :
  83    compopt=compopt
  84fi
  85
  86# Turn on extended globbing and programmable completion
  87shopt -s extglob progcomp
  88
  89# A lot of the following one-liners were taken directly from the
  90# completion examples provided with the bash 2.04 source distribution
  91
  92# Make directory commands see only directories
  93complete -d pushd
  94
  95# The following section lists completions that are redefined later
  96# Do NOT break these over multiple lines.
  97#
  98# START exclude -- do NOT remove this line
  99# bzcmp, bzdiff, bz*grep, bzless, bzmore intentionally not here, see Debian: #455510
 100complete -f -X '!*.?(t)bz?(2)' bunzip2 bzcat
 101complete -f -X '!*.@(zip|ZIP|jar|JAR|exe|EXE|pk3|war|wsz|ear|zargo|xpi|sxw|ott|od[fgpst]|epub)' unzip zipinfo
 102complete -f -X '*.Z' compress znew
 103# zcmp, zdiff, z*grep, zless, zmore intentionally not here, see Debian: #455510
 104complete -f -X '!*.@(Z|gz|tgz|Gz|dz)' gunzip zcat
 105complete -f -X '!*.Z' uncompress
 106# lzcmp, lzdiff intentionally not here, see Debian: #455510
 107complete -f -X '!*.lzma' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma
 108complete -f -X '!*.@(xz|lzma)' unxz xzcat
 109complete -f -X '!*.@(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)' ee
 110complete -f -X '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|GIF|JPG|JP?(E)G|TIF?(F)|PNG|P[BGP]M|BMP|X[BP]M|RLE|RGB|PCX|FITS|PM)' xv qiv
 111complete -f -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview
 112complete -f -X '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi
 113complete -f -X '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' kdvi
 114complete -f -X '!*.@(dvi|DVI)' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx
 115complete -f -X '!*.@(pdf|PDF)' acroread gpdf xpdf
 116complete -f -X '!*.@(?(e)ps|?(E)PS|pdf|PDF)' kpdf
 117complete -f -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF|dvi|DVI)?(.gz|.GZ|.bz2|.BZ2)|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)' evince
 118complete -f -X '!*.@(?(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)?(.?(gz|GZ|bz2|BZ2))' okular
 119complete -f -X '!*.@(?(e)ps|?(E)PS|pdf|PDF)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr
 120complete -f -X '!*.texi*' makeinfo texi2html
 121complete -f -X '!*.@(?(la)tex|?(LA)TEX|texi|TEXI|dtx|DTX|ins|INS)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi
 122complete -f -X '!*.@(mp3|MP3)' mpg123 mpg321 madplay
 123complete -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
 124complete -f -X '!*.@(avi|asf|wmv)' aviplay
 125complete -f -X '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay
 126complete -f -X '!*.@(mpg|mpeg|avi|mov|qt)' xanim
 127complete -f -X '!*.@(ogg|OGG|m3u|flac|spx)' ogg123
 128complete -f -X '!*.@(mp3|MP3|ogg|OGG|pls|m3u)' gqmpeg freeamp
 129complete -f -X '!*.fig' xfig
 130complete -f -X '!*.@(mid?(i)|MID?(I)|cmf|CMF)' playmidi
 131complete -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
 132complete -f -X '!*.@(m[eo]d|M[EO]D|s[3t]m|S[3T]M|xm|XM|it|IT)' modplugplay
 133complete -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
 134complete -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
 135complete -f -X '!*.@(exe|EXE|com|COM|scr|SCR|exe.so)' wine
 136complete -f -X '!*.@(zip|ZIP|z|Z|gz|GZ|tgz|TGZ)' bzme
 137complete -f -X '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx opera galeon curl dillo elinks amaya
 138complete -f -X '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|odt|ott|odm)' oowriter
 139complete -f -X '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|odp|otp)' ooimpress
 140complete -f -X '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|ods|ots)' oocalc
 141complete -f -X '!*.@(sxd|std|sda|sdd|odg|otg)' oodraw
 142complete -f -X '!*.@(sxm|smf|mml|odf)' oomath
 143complete -f -X '!*.odb' oobase
 144complete -f -X '!*.rpm' rpm2cpio
 145complete -f -X '!*.sqlite' sqlite3
 146complete -f -X '!*.aux' bibtex
 147complete -f -X '!*.po' poedit gtranslator kbabel lokalize
 148complete -f -X '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp
 149complete -f -X '!*.[Hh][Rr][Bb]' hbrun
 150complete -f -X '!*.ly' lilypond ly2dvi
 151# FINISH exclude -- do not remove this line
 152
 153# start of section containing compspecs that can be handled within bash
 154
 155# user commands see only users
 156complete -u su passwd write chfn groups slay w sux
 157
 158# bg completes with stopped jobs
 159complete -A stopped -P '"%' -S '"' bg
 160
 161# other job commands
 162complete -j -P '"%' -S '"' fg jobs disown
 163
 164# readonly and unset complete with shell variables
 165complete -v readonly unset
 166
 167# set completes with set options
 168complete -A setopt set
 169
 170# shopt completes with shopt options
 171complete -A shopt shopt
 172
 173# helptopics
 174complete -A helptopic help
 175
 176# unalias completes with aliases
 177complete -a unalias
 178
 179# bind completes with readline bindings (make this more intelligent)
 180complete -A binding bind
 181
 182# type and which complete on commands
 183complete -c command type which
 184
 185# builtin completes on builtins
 186complete -b builtin
 187
 188# start of section containing completion functions called by other functions
 189
 190# This function checks whether we have a given program on the system.
 191# No need for bulky functions in memory if we don't.
 192#
 193have()
 194{
 195    unset -v have
 196    PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 &>/dev/null &&
 197    have="yes"
 198}
 199
 200# use GNU sed if we have it, since its extensions are still used in our code
 201#
 202[ $USERLAND != GNU ] && have gsed && alias sed=gsed
 203
 204# This function checks whether a given readline variable
 205# is `on'.
 206#
 207_rl_enabled()
 208{
 209    [[ "$( bind -v )" = *$1+([[:space:]])on* ]]
 210}
 211
 212# This function shell-quotes the argument
 213quote()
 214{
 215    echo \'${1//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
 216}
 217
 218# This function quotes the argument in a way so that readline dequoting
 219# results in the original argument
 220quote_readline()
 221{
 222    if [ -n "$bash4" ] ; then
 223        # This function isn't really necessary on bash 4
 224        # See: http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
 225        echo "${1}"
 226        return
 227    fi
 228    local t="${1//\\/\\\\}"
 229    echo \'${t//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
 230}
 231
 232# This function shell-dequotes the argument
 233dequote()
 234{
 235    eval echo "$1" 2> /dev/null
 236}
 237
 238# Get the word to complete.
 239# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
 240# where the user is completing in the middle of a word.
 241# (For example, if the line is "ls foobar",
 242# and the cursor is here -------->   ^
 243# it will complete just "foo", not "foobar", which is what the user wants.)
 244# @param $1 string  (optional) Characters out of $COMP_WORDBREAKS which should
 245#     NOT be considered word breaks. This is useful for things like scp where
 246#     we want to return host:path and not only path.
 247#     NOTE: This parameter only applies to bash-4.
 248
 249_get_cword()
 250{
 251    if [ -n "$bash4" ] ; then
 252        __get_cword4 "$@"
 253    else
 254        __get_cword3
 255    fi
 256} # _get_cword()
 257
 258
 259# Get the word to complete on bash-3, where words are not broken by
 260# COMP_WORDBREAKS characters and the COMP_CWORD variables look like this, for
 261# example:
 262#
 263#     $ a b:c<TAB>
 264#     COMP_CWORD: 1
 265#     COMP_CWORDS:
 266#     0: a
 267#     1: b:c
 268#
 269# See also:
 270# _get_cword, main routine
 271# __get_cword4, bash-4 variant
 272#
 273__get_cword3()
 274{
 275    if [[ "${#COMP_WORDS[COMP_CWORD]}" -eq 0 ]] || [[ "$COMP_POINT" == "${#COMP_LINE}" ]]; then
 276        printf "%s" "${COMP_WORDS[COMP_CWORD]}"
 277    else
 278        local i
 279        local cur="$COMP_LINE"
 280        local index="$COMP_POINT"
 281        for (( i = 0; i <= COMP_CWORD; ++i )); do
 282            while [[
 283                # Current COMP_WORD fits in $cur?
 284                "${#cur}" -ge ${#COMP_WORDS[i]} &&
 285                # $cur doesn't match COMP_WORD?
 286                "${cur:0:${#COMP_WORDS[i]}}" != "${COMP_WORDS[i]}"
 287                ]]; do
 288                # Strip first character
 289                cur="${cur:1}"
 290                # Decrease cursor position
 291                index="$(( index - 1 ))"
 292            done
 293
 294            # Does found COMP_WORD matches COMP_CWORD?
 295            if [[ "$i" -lt "$COMP_CWORD" ]]; then
 296                # No, COMP_CWORD lies further;
 297                local old_size="${#cur}"
 298                cur="${cur#${COMP_WORDS[i]}}"
 299                local new_size="${#cur}"
 300                index="$(( index - old_size + new_size ))"
 301            fi
 302        done
 303
 304        if [[ "${COMP_WORDS[COMP_CWORD]:0:${#cur}}" != "$cur" ]]; then
 305            # We messed up! At least return the whole word so things
 306            # keep working
 307            printf "%s" "${COMP_WORDS[COMP_CWORD]}"
 308        else
 309            printf "%s" "${cur:0:$index}"
 310        fi
 311    fi
 312} # __get_cword3()
 313
 314
 315# Get the word to complete on bash-4, where words are splitted by
 316# COMP_WORDBREAKS characters (default is " \t\n\"'><=;|&(:") and the COMP_CWORD
 317# variables look like this, for example:
 318#
 319#     $ a b:c<TAB>
 320#     COMP_CWORD: 3
 321#     COMP_CWORDS:
 322#     0: a
 323#     1: b
 324#     2: :
 325#     3: c
 326#
 327# @oaram $1 string
 328# $1 string  (optional) Characters out of $COMP_WORDBREAKS which should
 329#     NOT be considered word breaks. This is useful for things like scp where
 330#     we want to return host:path and not only path.
 331# See also:
 332# _get_cword, main routine
 333# __get_cword3, bash-3 variant
 334#
 335__get_cword4()
 336{
 337    local i
 338    local LC_CTYPE=C
 339    local WORDBREAKS=$COMP_WORDBREAKS
 340    # Strip single quote (') and double quote (") from WORDBREAKS to
 341    # workaround a bug in bash-4.0, where quoted words are split
 342    # unintended, see:
 343    # http://www.mail-archive.com/bug-bash@gnu.org/msg06095.html
 344    # This fixes simple quoting (e.g. $ a "b<TAB> returns "b instead of b)
 345    # but still fails quoted spaces (e.g. $ a "b c<TAB> returns c instead
 346    # of "b c).
 347    WORDBREAKS=${WORDBREAKS//\"/}
 348    WORDBREAKS=${WORDBREAKS//\'/}
 349    if [ -n "$1" ]; then
 350        for (( i=0; i<${#1}; ++i )); do
 351            local char=${1:$i:1}
 352            WORDBREAKS=${WORDBREAKS//$char/}
 353        done
 354    fi
 355    local cur=${COMP_LINE:0:$COMP_POINT}
 356    local tmp=$cur
 357    local word_start=`expr "$tmp" : '.*['"$WORDBREAKS"']'`
 358    while [ "$word_start" -ge 2 ]; do
 359        # Get character before $word_start
 360        local char=${cur:$(( $word_start - 2 )):1}
 361        # If the WORDBREAK character isn't escaped, exit loop
 362        if [ "$char" != "\\" ]; then
 363            break
 364        fi
 365        # The WORDBREAK character is escaped;
 366        # Recalculate $word_start
 367        tmp=${COMP_LINE:0:$(( $word_start - 2 ))}
 368        word_start=`expr "$tmp" : '.*['"$WORDBREAKS"']'`
 369    done
 370
 371    cur=${cur:$word_start}
 372    printf "%s" "$cur"
 373} # __get_cword4()
 374
 375
 376# This function performs file and directory completion. It's better than
 377# simply using 'compgen -f', because it honours spaces in filenames.
 378# If passed -d, it completes only on directories. If passed anything else,
 379# it's assumed to be a file glob to complete on.
 380#
 381_filedir()
 382{
 383    local IFS=$'\t\n' xspec
 384
 385    _expand || return 0
 386
 387    local -a toks
 388    local tmp
 389
 390    # TODO: I've removed a "[ -n $tmp ] &&" before `echo $tmp',
 391    #       and everything works again. If this bug
 392    #       suddenly appears again (i.e. "cd /b<TAB>"
 393    #       becomes "cd /"), remember to check for
 394    #       other similar conditionals (here and
 395    #       _filedir_xspec()). --David
 396    # NOTE: The comment above has been moved outside of the subshell below,
 397    #       because quotes-in-comments-in-a-subshell cause errors on
 398    #       bash-3.1.  See also:
 399    #       http://www.mail-archive.com/bug-bash@gnu.org/msg01667.html
 400    toks=( ${toks[@]-} $(
 401    compgen -d -- "$(quote_readline "$cur")" | {
 402    while read -r tmp; do
 403        echo $tmp
 404    done
 405}
 406))
 407
 408if [[ "$1" != -d ]]; then
 409    xspec=${1:+"!*.$1"}
 410    toks=( ${toks[@]-} $(
 411    compgen -f -X "$xspec" -- "$(quote_readline "$cur")" | {
 412    while read -r tmp; do
 413        [ -n $tmp ] && echo $tmp
 414    done
 415}
 416))
 417    fi
 418
 419    COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" )
 420}
 421
 422# This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it
 423# easier to support both "--foo bar" and "--foo=bar" style completions.
 424# Returns 0 if current option was split, 1 otherwise.
 425#
 426_split_longopt()
 427{
 428    if [[ "$cur" == --?*=* ]]; then
 429        # Cut also backslash before '=' in case it ended up there
 430        # for some reason.
 431        prev="${cur%%?(\\)=*}"
 432        cur="${cur#*=}"
 433        return 0
 434    fi
 435
 436    return 1
 437}
 438
 439# This function tries to parse the output of $command --help
 440#
 441_parse_help() {
 442    local cmd
 443    cmd=$1
 444    $cmd --help | \
 445    grep -- "^[[:space:]]*-" | \
 446    tr "," " " | \
 447    awk '{print $1; if ($2 ~ /-.*/) { print $2 } }' | \
 448    sed -e "s:=.*::g"
 449}
 450
 451# This function completes on signal names
 452#
 453_signals()
 454{
 455    local i
 456
 457    # standard signal completion is rather braindead, so we need
 458    # to hack around to get what we want here, which is to
 459    # complete on a dash, followed by the signal name minus
 460    # the SIG prefix
 461    COMPREPLY=( $( compgen -A signal SIG${cur#-} ))
 462    for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
 463        COMPREPLY[i]=-${COMPREPLY[i]#SIG}
 464    done
 465}
 466
 467# This function completes on configured network interfaces
 468#
 469_configured_interfaces()
 470{
 471    if [ -f /etc/debian_version ]; then
 472        # Debian system
 473        COMPREPLY=( $( compgen -W "$( sed -ne 's|^iface \([^ ]\+\).*$|\1|p' \
 474            /etc/network/interfaces )" -- "$cur" ) )
 475    elif [ -f /etc/SuSE-release ]; then
 476        # SuSE system
 477        COMPREPLY=( $( compgen -W "$( command ls \
 478            /etc/sysconfig/network/ifcfg-* | \
 479            sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
 480    elif [ -f /etc/pld-release ]; then
 481        # PLD Linux
 482        COMPREPLY=( $( compgen -W "$( command ls -B \
 483            /etc/sysconfig/interfaces | \
 484            sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
 485    else
 486        # Assume Red Hat
 487        COMPREPLY=( $( compgen -W "$( command ls \
 488            /etc/sysconfig/network-scripts/ifcfg-* | \
 489            sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
 490    fi
 491}
 492
 493# This function completes on available kernels
 494#
 495_kernel_versions()
 496{
 497    COMPREPLY=( $( compgen -W '$( command ls /lib/modules )' -- "$cur" ) )
 498}
 499
 500# This function completes on all available network interfaces
 501# -a: restrict to active interfaces only
 502# -w: restrict to wireless interfaces only
 503#
 504_available_interfaces()
 505{
 506    local cmd
 507
 508    if [ "${1:-}" = -w ]; then
 509        cmd="iwconfig"
 510    elif [ "${1:-}" = -a ]; then
 511        cmd="ifconfig"
 512    else
 513        cmd="ifconfig -a"
 514    fi
 515
 516    COMPREPLY=( $( eval $cmd 2>/dev/null | \
 517        awk '/^[^[:space:]]/ { print $1 }' ) )
 518    COMPREPLY=( $( compgen -W '${COMPREPLY[@]/%[[:punct:]]/}' -- "$cur" ) )
 519}
 520
 521# This function expands tildes in pathnames
 522#
 523_expand()
 524{
 525    # FIXME: Why was this here?
 526    #[ "$cur" != "${cur%\\}" ] && cur="$cur\\"
 527
 528    # Expand ~username type directory specifications.  We want to expand
 529    # ~foo/... to /home/foo/... to avoid problems when $cur starting with
 530    # a tilde is fed to commands and ending up quoted instead of expanded.
 531
 532    if [[ "$cur" == \~*/* ]]; then
 533        eval cur=$cur
 534    elif [[ "$cur" == \~* ]]; then
 535        cur=${cur#\~}
 536        COMPREPLY=( $( compgen -P '~' -u "$cur" ) )
 537        [ ${#COMPREPLY[@]} -eq 1 ] && eval COMPREPLY[0]=${COMPREPLY[0]}
 538        return ${#COMPREPLY[@]}
 539    fi
 540}
 541
 542# This function completes on process IDs.
 543# AIX and Solaris ps prefers X/Open syntax.
 544[ $UNAME = SunOS -o $UNAME = AIX ] &&
 545_pids()
 546{
 547    COMPREPLY=( $( compgen -W '$( command ps -efo pid | sed 1d )' -- "$cur" ))
 548} ||
 549_pids()
 550{
 551    COMPREPLY=( $( compgen -W '$( command ps axo pid= )' -- "$cur" ) )
 552}
 553
 554# This function completes on process group IDs.
 555# AIX and SunOS prefer X/Open, all else should be BSD.
 556[ $UNAME = SunOS -o $UNAME = AIX ] &&
 557_pgids()
 558{
 559    COMPREPLY=( $( compgen -W '$( command ps -efo pgid | sed 1d )' -- "$cur" ))
 560} ||
 561_pgids()
 562{
 563    COMPREPLY=( $( compgen -W '$( command ps axo pgid= )' -- "$cur" ))
 564}
 565
 566# This function completes on process names.
 567# AIX and SunOS prefer X/Open, all else should be BSD.
 568[ $UNAME = SunOS -o $UNAME = AIX ] &&
 569_pnames()
 570{
 571    COMPREPLY=( $( compgen -W '$( command ps -efo comm | \
 572    sed -e 1d -e "s:.*/::" -e "s/^-//" \
 573    -e "s/^<defunct>$//")' \
 574    -- "$cur" ) )
 575} ||
 576_pnames()
 577{
 578    # FIXME: completes "[kblockd/0]" to "0". Previously it was completed
 579    # to "kblockd" which isn't correct either. "kblockd/0" would be
 580    # arguably most correct, but killall from psmisc 22 treats arguments
 581    # containing "/" specially unless -r is given so that wouldn't quite
 582    # work either. Perhaps it'd be best to not complete these to anything
 583    # for now.
 584    # Not using "ps axo comm" because under some Linux kernels, it
 585    # truncates command names (see e.g. http://bugs.debian.org/497540#19)
 586    COMPREPLY=( $( compgen -W '$( command ps axo command= | \
 587    sed -e "s/ .*//; s:.*/::; s/:$//;" \
 588    -e "s/^[[(-]//; s/[])]$//" \
 589    -e "s/^<defunct>$//")' \
 590    -- "$cur" ) )
 591}
 592
 593# This function completes on user IDs
 594#
 595_uids()
 596{
 597    if type getent &>/dev/null; then
 598        COMPREPLY=( $( compgen -W '$( getent passwd | cut -d: -f3 )' -- "$cur" ) )
 599    elif type perl &>/dev/null; then
 600        COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"' )' -- "$cur" ) )
 601    else
 602        # make do with /etc/passwd
 603        COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/passwd )' -- "$cur" ) )
 604    fi
 605}
 606
 607# This function completes on group IDs
 608#
 609_gids()
 610{
 611    if type getent &>/dev/null; then
 612        COMPREPLY=( $( compgen -W '$( getent group | cut -d: -f3 )' \
 613            -- "$cur" ) )
 614    elif type perl &>/dev/null; then
 615        COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"' )' -- "$cur" ) )
 616    else
 617        # make do with /etc/group
 618        COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/group )' -- "$cur" ) )
 619    fi
 620}
 621
 622# This function completes on services
 623#
 624_services()
 625{
 626    local sysvdir famdir
 627    [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d || sysvdir=/etc/init.d
 628    famdir=/etc/xinetd.d
 629    COMPREPLY=( $( builtin echo $sysvdir/!(*.rpm@(orig|new|save)|*~|functions)) )
 630
 631    if [ -d $famdir ]; then
 632        COMPREPLY=( "${COMPREPLY[@]}" $( builtin echo $famdir/!(*.rpm@(orig|new|save)|*~)) )
 633    fi
 634
 635    COMPREPLY=( $( compgen -W '${COMPREPLY[@]#@($sysvdir|$famdir)/}' -- "$cur" ) )
 636}
 637
 638# This function completes on modules
 639#
 640_modules()
 641{
 642    local modpath
 643    modpath=/lib/modules/$1
 644    COMPREPLY=( $( compgen -W "$( command ls -R $modpath | \
 645        sed -ne 's/^\(.*\)\.k\?o\(\|.gz\)$/\1/p' )" -- "$cur" ) )
 646}
 647
 648# This function completes on installed modules
 649#
 650_installed_modules()
 651{
 652    COMPREPLY=( $( compgen -W "$( PATH="$PATH:/sbin" lsmod | \
 653        awk '{if (NR != 1) print $1}' )" -- "$1" ) )
 654}
 655
 656# This function completes on user:group format
 657#
 658_usergroup()
 659{
 660    local IFS=$'\n'
 661    cur=${cur//\\\\ / }
 662    if [[ $cur = *@(\\:|.)* ]] && [ -n "$bash205" ]; then
 663        user=${cur%%*([^:.])}
 664        COMPREPLY=( $(compgen -P ${user/\\\\} -g -- ${cur##*[.:]}) )
 665    elif [[ $cur = *:* ]] && [ -n "$bash205" ]; then
 666        COMPREPLY=( $( compgen -g -- ${cur##*[.:]} ) )
 667    else
 668        COMPREPLY=( $( compgen -S : -u -- "$cur" ) )
 669    fi
 670}
 671
 672# This function completes on valid shells
 673#
 674_shells()
 675{
 676    COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W '$( grep "^[[:space:]]*/" \
 677    /etc/shells 2>/dev/null )' -- "$cur" ) )
 678}
 679
 680# Get real command.
 681# - arg: $1  Command
 682# - stdout:  Filename of command in PATH with possible symbolic links resolved.
 683#            Empty string if command not found.
 684# - return:  True (0) if command found, False (> 0) if not.
 685_realcommand() {
 686    type -P "$1" > /dev/null && {
 687    if type -p realpath > /dev/null; then
 688        realpath "$(type -P "$1")"
 689    elif type -p readlink > /dev/null; then
 690        readlink -f "$(type -P "$1")"
 691    else
 692        type -P "$1"
 693    fi
 694}
 695}
 696
 697
 698# this function count the number of mandatory args
 699#
 700_count_args()
 701{
 702    args=1
 703    for (( i=1; i < COMP_CWORD; i++ )); do
 704        if [[ "${COMP_WORDS[i]}" != -* ]]; then
 705            args=$(($args+1))
 706        fi
 707    done
 708}
 709
 710# This function completes on PCI IDs
 711#
 712_pci_ids()
 713{
 714    COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
 715    "$( PATH="$PATH:/sbin" lspci -n | awk '{print $3}')" -- "$cur" ) )
 716}
 717
 718# This function completes on USB IDs
 719#
 720_usb_ids()
 721{
 722    COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
 723    "$( PATH="$PATH:/sbin" lsusb | awk '{print $6}' )" -- "$cur" ) )
 724}
 725
 726# start of section containing completion functions for external programs
 727
 728# a little help for FreeBSD ports users
 729[ $UNAME = FreeBSD ] && complete -W 'index search fetch fetch-list \
 730extract patch configure build install reinstall \
 731deinstall clean clean-depends kernel buildworld' make
 732
 733# This completes on a list of all available service scripts for the
 734# 'service' command and/or the SysV init.d directory, followed by
 735# that script's available commands
 736#
 737{ have service || [ -d /etc/init.d/ ]; } &&
 738    _service()
 739    {
 740        local cur prev sysvdir
 741
 742        COMPREPLY=()
 743        prev=${COMP_WORDS[COMP_CWORD-1]}
 744        cur=`_get_cword`
 745
 746        # don't complete for things like killall, ssh and mysql if it's
 747        # the standalone command, rather than the init script
 748        [[ ${COMP_WORDS[0]} != @(*init.d/!(functions|~)|service) ]] && return 0
 749
 750        # don't complete past 2nd token
 751        [ $COMP_CWORD -gt 2 ] && return 0
 752
 753        [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d \
 754        || sysvdir=/etc/init.d
 755
 756        if [[ $COMP_CWORD -eq 1 ]] && [[ $prev == "service" ]]; then
 757            _services
 758        else
 759            COMPREPLY=( $( compgen -W '`sed -ne "y/|/ /; \
 760            s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\1/p" \
 761            $sysvdir/${prev##*/} 2>/dev/null`' -- "$cur" ) )
 762        fi
 763
 764        return 0
 765    } &&
 766    complete -F _service service
 767    [ -d /etc/init.d/ ] && complete -F _service $default \
 768    $(for i in /etc/init.d/*; do echo ${i##*/}; done)
 769
 770    # chown(1) completion
 771    #
 772    _chown()
 773    {
 774        local cur prev split=false
 775        cur=`_get_cword`
 776        prev=${COMP_WORDS[COMP_CWORD-1]}
 777
 778        _split_longopt && split=true
 779
 780        case "$prev" in
 781            --from)
 782                _usergroup
 783                return 0
 784                ;;
 785            --reference)
 786                _filedir
 787                return 0
 788                ;;
 789        esac
 790
 791        $split && return 0
 792
 793        # options completion
 794        if [[ "$cur" == -* ]]; then
 795            COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes \
 796            --dereference --no-dereference --from --silent --quiet \
 797            --reference --recursive --verbose --help --version' -- "$cur" ) )
 798        else
 799            _count_args
 800
 801            case $args in
 802                1)
 803                    _usergroup
 804                    ;;
 805                *)
 806                    _filedir
 807                    ;;
 808            esac
 809        fi
 810    }
 811    complete -F _chown $filenames chown
 812
 813    # chgrp(1) completion
 814    #
 815    _chgrp()
 816    {
 817        local cur prev split=false
 818
 819        COMPREPLY=()
 820        cur=`_get_cword`
 821        cur=${cur//\\\\/}
 822        prev=${COMP_WORDS[COMP_CWORD-1]}
 823
 824        _split_longopt && split=true
 825
 826        if [[ "$prev" == --reference ]]; then
 827            _filedir
 828            return 0
 829        fi
 830
 831        $split && return 0
 832
 833        # options completion
 834        if [[ "$cur" == -* ]]; then
 835            COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes \
 836            --dereference --no-dereference --silent --quiet \
 837            --reference --recursive --verbose --help --version' -- "$cur" ) )
 838            return 0
 839        fi
 840
 841        # first parameter on line or first since an option?
 842        if [ $COMP_CWORD -eq 1 ] && [[ "$cur" != -* ]] || \
 843            [[ "$prev" == -* ]] && [ -n "$bash205" ]; then
 844            local IFS=$'\n'
 845            COMPREPLY=( $( compgen -g "$cur" 2>/dev/null ) )
 846        else
 847            _filedir || return 0
 848        fi
 849
 850        return 0
 851    }
 852    complete -F _chgrp $filenames chgrp
 853
 854    # umount(8) completion. This relies on the mount point being the third
 855    # space-delimited field in the output of mount(8)
 856    #
 857    _umount()
 858    {
 859        local cur IFS=$'\n'
 860
 861        COMPREPLY=()
 862        cur=`_get_cword`
 863
 864        COMPREPLY=( $( compgen -W '$( mount | cut -d" " -f 3 )' -- "$cur" ) )
 865
 866        return 0
 867    }
 868    complete -F _umount $dirnames umount
 869
 870    # mount(8) completion. This will pull a list of possible mounts out of
 871    # /etc/{,v}fstab, unless the word being completed contains a ':', which
 872    # would indicate the specification of an NFS server. In that case, we
 873    # query the server for a list of all available exports and complete on
 874    # that instead.
 875    #
 876    _mount()
 877    {
 878        local cur i sm host prev
 879
 880        COMPREPLY=()
 881        cur=`_get_cword`
 882        [[ "$cur" == \\ ]] && cur="/"
 883        prev=${COMP_WORDS[COMP_CWORD-1]}
 884
 885        for i in {,/usr}/{,s}bin/showmount; do [ -x $i ] && sm=$i && break; done
 886
 887        if [ -n "$sm" ] && [[ "$cur" == *:* ]]; then
 888            COMPREPLY=( $( compgen -W "$( $sm -e ${cur%%:*} | sed 1d | \
 889                awk '{print $1}' )" -- "$cur" ) )
 890        elif [[ "$cur" == //* ]]; then
 891            host=${cur#//}
 892            host=${host%%/*}
 893            if [ -n "$host" ]; then
 894                COMPREPLY=( $( compgen -P "//$host" -W \
 895                    "$( smbclient -d 0 -NL $host 2>/dev/null |
 896                    sed -ne '/^['"$'\t '"']*Sharename/,/^$/p' |
 897                    sed -ne '3,$s|^[^A-Za-z]*\([^'"$'\t '"']*\).*$|/\1|p' )" \
 898                    -- "${cur#//$host}" ) )
 899            fi
 900        elif [ -r /etc/vfstab ]; then
 901            # Solaris
 902            COMPREPLY=( $( compgen -W "$( awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' /etc/vfstab )" -- "$cur" ) )
 903        elif [ ! -e /etc/fstab ]; then
 904            # probably Cygwin
 905            COMPREPLY=( $( compgen -W "$( mount | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' )" -- "$cur" ) )
 906        else
 907            # probably Linux
 908            if [ $prev = -L ]; then
 909                COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*LABEL=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- "$cur" ) )
 910            elif [ $prev = -U ]; then
 911                COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*UUID=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- "$cur" ) )
 912            else
 913                COMPREPLY=( $( compgen -W "$( awk '! /^[ \t]*#/ {if ($2 ~ /\//) print $2}' /etc/fstab )" -- "$cur" ) )
 914            fi
 915        fi
 916
 917        return 0
 918    }
 919    complete -F _mount $default $dirnames mount
 920
 921    # Linux rmmod(8) completion. This completes on a list of all currently
 922    # installed kernel modules.
 923    #
 924    have rmmod && {
 925    _rmmod()
 926    {
 927        local cur
 928
 929        COMPREPLY=()
 930        cur=`_get_cword`
 931
 932        _installed_modules "$cur"
 933        return 0
 934    }
 935    complete -F _rmmod rmmod
 936
 937    # Linux insmod(8), modprobe(8) and modinfo(8) completion. This completes on a
 938    # list of all available modules for the version of the kernel currently
 939    # running.
 940    #
 941    _insmod()
 942    {
 943        local cur prev modpath
 944
 945        COMPREPLY=()
 946        cur=`_get_cword`
 947        prev=${COMP_WORDS[COMP_CWORD-1]}
 948
 949        # behave like lsmod for modprobe -r
 950        if [ $1 = "modprobe" ] &&
 951            [ "${COMP_WORDS[1]}" = "-r" ]; then
 952            _installed_modules "$cur"
 953            return 0
 954        fi
 955
 956        # do filename completion if we're giving a path to a module
 957        if [[ "$cur" == */* ]]; then
 958            _filedir '@(?(k)o?(.gz))'
 959            return 0
 960        fi
 961
 962        if [ $COMP_CWORD -gt 1 ] &&
 963            [[ "${COMP_WORDS[COMP_CWORD-1]}" != -* ]]; then
 964            # do module parameter completion
 965            COMPREPLY=( $( compgen -W "$( /sbin/modinfo -p ${COMP_WORDS[1]} | \
 966                cut -d: -f1 )" -- "$cur" ) )
 967        else
 968            _modules $(uname -r)
 969        fi
 970
 971        return 0
 972    }
 973    complete -F _insmod $filenames insmod modprobe modinfo
 974}
 975
 976# renice(8) completion
 977#
 978_renice()
 979{
 980    local command cur curopt i
 981
 982    COMPREPLY=()
 983    cur=`_get_cword`
 984    command=$1
 985
 986    i=0
 987    # walk back through command line and find last option
 988    while [ $i -le $COMP_CWORD -a ${#COMPREPLY[@]} -eq 0 ]; do
 989        curopt=${COMP_WORDS[COMP_CWORD-$i]}
 990        case "$curopt" in
 991            -u)
 992                COMPREPLY=( $( compgen -u -- "$cur" ) )
 993                ;;
 994            -g)
 995                _pgids
 996                ;;
 997            -p|$command)
 998                _pids
 999                ;;
1000        esac
1001        i=$(( ++i ))
1002    done
1003}
1004complete -F _renice renice
1005
1006# kill(1) completion
1007#
1008_kill()
1009{
1010    local cur
1011
1012    COMPREPLY=()
1013    cur=`_get_cword`
1014
1015    if [ $COMP_CWORD -eq 1 ] && [[ "$cur" == -* ]]; then
1016        # return list of available signals
1017        _signals
1018    else
1019        # return list of available PIDs
1020        _pids
1021    fi
1022}
1023complete -F _kill kill
1024
1025# killall(1) (Linux and FreeBSD) and pkill(1) completion.
1026#
1027[ $UNAME = Linux -o $UNAME = FreeBSD ] || have pkill &&
1028_killall()
1029{
1030    local cur
1031
1032    COMPREPLY=()
1033    cur=`_get_cword`
1034
1035    if [ $COMP_CWORD -eq 1 ] && [[ "$cur" == -* ]]; then
1036        _signals
1037    else
1038        _pnames
1039    fi
1040
1041    return 0
1042}
1043[ $UNAME = Linux -o $UNAME = FreeBSD ] && complete -F _killall killall
1044have pkill && complete -F _killall pkill
1045
1046# pgrep(1) completion.
1047#
1048[ $UNAME = Linux ] || have pgrep &&
1049_pgrep()
1050{
1051    local cur
1052
1053    COMPREPLY=()
1054    cur=`_get_cword`
1055
1056    _pnames
1057
1058    return 0
1059}
1060have pgrep && complete -F _pgrep pgrep
1061
1062# Linux pidof(8) completion.
1063[ $UNAME = Linux ] && complete -F _pgrep pidof
1064
1065# Red Hat & Debian GNU/Linux if{up,down} completion
1066#
1067[ $USERLAND = GNU ] && { have ifup || have ifdown; } &&
1068_ifupdown()
1069{
1070    local cur
1071
1072    COMPREPLY=()
1073    cur=`_get_cword`
1074
1075    if [ $COMP_CWORD -eq 1 ]; then
1076        _configured_interfaces
1077        COMPREPLY=( $(compgen -W '${COMPREPLY[@]}' -- "$cur") )
1078    fi
1079
1080    return 0
1081} &&
1082complete -F _ifupdown ifup ifdown
1083[ $USERLAND = GNU ] && have ifstatus && complete -F _ifupdown ifstatus
1084
1085# Linux ipsec(8) completion (for FreeS/WAN)
1086#
1087[ $UNAME = Linux ] && have ipsec &&
1088_ipsec()
1089{
1090    local cur
1091
1092    COMPREPLY=()
1093    cur=`_get_cword`
1094
1095
1096    if [ $COMP_CWORD -eq 1 ]; then
1097        COMPREPLY=( $( compgen -W 'auto barf eroute klipsdebug look \
1098        manual pluto ranbits rsasigkey \
1099        setup showdefaults showhostkey spi \
1100        spigrp tncfg whack' -- "$cur" ) )
1101        return 0
1102    fi
1103
1104    case ${COMP_WORDS[1]} in
1105        auto)
1106            COMPREPLY=( $( compgen -W '--asynchronous --up --add --delete \
1107                --replace --down --route --unroute \
1108                --ready --status --rereadsecrets' \
1109                -- "$cur" ) )
1110            ;;
1111        manual)
1112            COMPREPLY=( $( compgen -W '--up --down --route --unroute \
1113                --union' -- "$cur" ) )
1114            ;;
1115        ranbits)
1116            COMPREPLY=( $( compgen -W '--quick --continuous --bytes' \
1117                -- "$cur" ) )
1118            ;;
1119        setup)
1120            COMPREPLY=( $( compgen -W '--start --stop --restart' -- "$cur" ) )
1121            ;;
1122        *)
1123            ;;
1124    esac
1125
1126    return 0
1127} &&
1128complete -F _ipsec ipsec
1129
1130# This function provides simple user@host completion
1131#
1132_user_at_host() {
1133    local cur
1134
1135    COMPREPLY=()
1136    cur=`_get_cword`
1137
1138    if [[ $cur == *@* ]]; then
1139        _known_hosts_real "$cur"
1140    else
1141        COMPREPLY=( $( compgen -u -- "$cur" ) )
1142    fi
1143
1144    return 0
1145}
1146shopt -u hostcomplete && complete -F _user_at_host $nospace talk ytalk finger
1147
1148# NOTE: Using this function as a helper function is deprecated.  Use
1149#       `_known_hosts_real' instead.
1150_known_hosts()
1151{
1152    local options
1153    COMPREPLY=()
1154
1155    # NOTE: Using `_known_hosts' as a helper function and passing options
1156    #       to `_known_hosts' is deprecated: Use `_known_hosts_real' instead.
1157    [ "$1" = -a ] || [ "$2" = -a ] && options=-a
1158    [ "$1" = -c ] || [ "$2" = -c ] && options="$options -c"
1159    _known_hosts_real $options "$(_get_cword)"
1160}
1161
1162# Helper function for completing _known_hosts.
1163# This function performs host completion based on ssh's known_hosts files.
1164# Also hosts from HOSTFILE (compgen -A hostname) are added, unless
1165# COMP_KNOWN_HOSTS_WITH_HOSTFILE is set to an empty value.
1166# Usage: _known_hosts_real [OPTIONS] CWORD
1167# Options:  -a             Use aliases
1168#           -c             Use `:' suffix
1169#           -F configfile  Use `configfile' for configuration settings
1170#           -p PREFIX      Use PREFIX
1171# Return: Completions, starting with CWORD, are added to COMPREPLY[]
1172_known_hosts_real()
1173{
1174    local configfile flag prefix
1175    local cur curd awkcur user suffix aliases hosts i host
1176    local -a kh khd config
1177
1178    local OPTIND=1
1179    while getopts "acF:p:" flag "$@"; do
1180        case $flag in
1181            a) aliases='yes' ;;
1182            c) suffix=':' ;;
1183            F) configfile=$OPTARG ;;
1184            p) prefix=$OPTARG ;;
1185        esac
1186    done
1187    [ $# -lt $OPTIND ] && echo "error: $FUNCNAME: missing mandatory argument CWORD"
1188    cur=${!OPTIND}; let "OPTIND += 1"
1189    [ $# -ge $OPTIND ] && echo "error: $FUNCNAME("$@"): unprocessed arguments:"\
1190    $(while [ $# -ge $OPTIND ]; do echo ${!OPTIND}; shift; done)
1191
1192    [[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
1193    kh=()
1194
1195    # ssh config files
1196    if [ -n "$configfile" ]; then
1197        [ -r "$configfile" ] &&
1198        config=( "${config[@]}" "$configfile" )
1199    else
1200        [ -r /etc/ssh/ssh_config ] &&
1201        config=( "${config[@]}" "/etc/ssh/ssh_config" )
1202        [ -r "${HOME}/.ssh/config" ] &&
1203        config=( "${config[@]}" "${HOME}/.ssh/config" )
1204        [ -r "${HOME}/.ssh2/config" ] &&
1205        config=( "${config[@]}" "${HOME}/.ssh2/config" )
1206    fi
1207
1208    # Known hosts files from configs
1209    if [ ${#config[@]} -gt 0 ]; then
1210        local OIFS=$IFS IFS=$'\n'
1211        local -a tmpkh
1212        # expand paths (if present) to global and user known hosts files
1213        # TODO(?): try to make known hosts files with more than one consecutive
1214        #          spaces in their name work (watch out for ~ expansion
1215        #          breakage! Alioth#311595)
1216        tmpkh=( $( sed -ne 's/^[ \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 '"']*\(.*\)$/\2/p' "${config[@]}" | sort -u ) )
1217        for i in "${tmpkh[@]//\"/}"; do
1218            i=$( eval echo "$i" ) # expand ~
1219            [ -r "$i" ] && kh=( "${kh[@]}" "$i" )
1220        done
1221        IFS=$OIFS
1222    fi
1223
1224    # Global known_hosts files
1225    if [ -z "$configfile" ]; then
1226        [ -r /etc/ssh/ssh_known_hosts ] &&
1227        kh=( "${kh[@]}" /etc/ssh/ssh_known_hosts )
1228        [ -r /etc/ssh/ssh_known_hosts2 ] &&
1229        kh=( "${kh[@]}" /etc/ssh/ssh_known_hosts2 )
1230        [ -r /etc/known_hosts ] &&
1231        kh=( "${kh[@]}" /etc/known_hosts )
1232        [ -r /etc/known_hosts2 ] &&
1233        kh=( "${kh[@]}" /etc/known_hosts2 )
1234        [ -d /etc/ssh2/knownhosts ] &&
1235        khd=( "${khd[@]}" /etc/ssh2/knownhosts/*pub )
1236    fi
1237
1238    # User known_hosts files
1239    if [ -z "$configfile" ]; then
1240        [ -r ~/.ssh/known_hosts ] &&
1241        kh=( "${kh[@]}" ~/.ssh/known_hosts )
1242        [ -r ~/.ssh/known_hosts2 ] &&
1243        kh=( "${kh[@]}" ~/.ssh/known_hosts2 )
1244        [ -d ~/.ssh2/hostkeys ] &&
1245        khd=( "${khd[@]}" ~/.ssh2/hostkeys/*pub )
1246    fi
1247
1248    # If we have known_hosts files to use
1249    if [ ${#kh[@]} -gt 0 -o ${#khd[@]} -gt 0 -o -n "$configfile" ]; then
1250        # Escape slashes and dots in paths for awk
1251        awkcur=${cur//\//\\\/}
1252        awkcur=${awkcur//\./\\\.}
1253        curd=$awkcur
1254
1255        if [[ "$awkcur" == [0-9]*.* ]]; then
1256            # Digits followed by a dot - just search for that
1257            awkcur="^$awkcur.*"
1258        elif [[ "$awkcur" == [0-9]* ]]; then
1259            # Digits followed by no dot - search for digits followed
1260            # by a dot
1261            awkcur="^$awkcur.*\."
1262        elif [ -z "$awkcur" ]; then
1263            # A blank - search for a dot or an alpha character
1264            awkcur="[a-z.]"
1265        else
1266            awkcur="^$awkcur"
1267        fi
1268
1269        if [ ${#kh[@]} -gt 0 ]; then
1270            # FS needs to look for a comma separated list
1271            COMPREPLY=( $( awk 'BEGIN {FS=","}
1272            /^\s*[^|\#]/ {for (i=1; i<=2; ++i) { \
1273            gsub(" .*$", "", $i); \
1274            gsub("[\\[\\]]", "", $i); \
1275            gsub(":[0-9]+$", "", $i); \
1276            if ($i ~ /'"$awkcur"'/) {print $i} \
1277            }}' "${kh[@]}" 2>/dev/null ) )
1278        fi
1279        if [ ${#khd[@]} -gt 0 ]; then
1280            # Needs to look for files called
1281            # .../.ssh2/key_22_<hostname>.pub
1282            # dont fork any processes, because in a cluster environment,
1283            # there can be hundreds of hostkeys
1284            for i in "${khd[@]}" ; do
1285                if [[ "$i" == *key_22_$awkcurd*.pub ]] && [ -r "$i" ] ; then
1286                    host=${i/#*key_22_/}
1287                    host=${host/%.pub/}
1288                    COMPREPLY=( "${COMPREPLY[@]}" $host )
1289                fi
1290            done
1291        fi
1292        # append any available aliases from config files
1293        if [ ${#config[@]} -gt 0 ] && [ -n "$aliases" ]; then
1294            local host_aliases=$( sed -ne 's/^[ \t]*[Hh][Oo][Ss][Tt]\([Nn][Aa][Mm][Ee]\)\?['"$'\t '"']\+\([^#*?]*\)\(#.*\)\?$/\2/p' "${config[@]}" )
1295            hosts=$( compgen -W "$host_aliases" -- "$cur" )
1296            COMPREPLY=( "${COMPREPLY[@]}" $hosts )
1297        fi
1298
1299        # Add hosts reported by avahi, if it's available
1300        # and if the daemon is started.
1301        # The original call to avahi-browse also had "-k", to avoid
1302        #  lookups into avahi's services DB. We don't need the name
1303        #  of the service, and if it contains ";", it may mistify
1304        #  the result. But on Gentoo (at least), -k isn't available
1305        #  (even if mentioned in the manpage), so...
1306
1307        # This feature is disabled because it does not scale to
1308        #  larger networks. See:
1309        # https://bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/510591
1310        #if type avahi-browse >&/dev/null; then
1311        #    if [ -n "$(pidof avahi-daemon)" ]; then
1312        #        COMPREPLY=( "${COMPREPLY[@]}" $(
1313        #        compgen -W "$( avahi-browse -cpr _workstation._tcp | \
1314        #        grep ^= | cut -d\; -f7 | sort -u )" -- "$cur" ) )
1315        #    fi
1316        #fi
1317
1318        # apply suffix and prefix
1319        for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
1320            COMPREPLY[i]=$prefix$user${COMPREPLY[i]}$suffix
1321        done
1322    fi
1323
1324    # Add results of normal hostname completion, unless `COMP_KNOWN_HOSTS_WITH_HOSTFILE'
1325    # is set to an empty value.
1326    if [ -n "${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1}" ]; then
1327        COMPREPLY=( "${COMPREPLY[@]}" $( compgen -A hostname -P "$prefix$user" -S "$suffix" -- "$cur" ) )
1328    fi
1329
1330    return 0
1331}
1332complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 \
1333ping ping6 fping fping6 telnet host nslookup rsh rlogin ftp dig ssh-installkeys mtr
1334
1335# This meta-cd function observes the CDPATH variable, so that cd additionally
1336# completes on directories under those specified in CDPATH.
1337#
1338_cd()
1339{
1340    local IFS=$'\t\n' cur=`_get_cword` i j k
1341
1342    # try to allow variable completion
1343    if [[ "$cur" == ?(\\)\$* ]]; then
1344        COMPREPLY=( $( compgen -v -P '$' -- "${cur#?(\\)$}" ) )
1345        return 0
1346    fi
1347
1348    # Enable -o filenames option, see Debian bug #272660
1349    compgen -f /non-existing-dir/ >/dev/null
1350
1351    # Use standard dir completion if no CDPATH or parameter starts with /,
1352    # ./ or ../
1353    if [ -z "${CDPATH:-}" ] || [[ "$cur" == ?(.)?(.)/* ]]; then
1354        _filedir -d
1355        return 0
1356    fi
1357
1358    local -r mark_dirs=$(_rl_enabled mark-directories && echo y)
1359    local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y)
1360
1361    # we have a CDPATH, so loop on its contents
1362    for i in ${CDPATH//:/$'\t'}; do
1363        # create an array of matched subdirs
1364        k="${#COMPREPLY[@]}"
1365        for j in $( compgen -d $i/$cur ); do
1366            if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
1367                j="${j}/"
1368            fi
1369            COMPREPLY[k++]=${j#$i/}
1370        done
1371    done
1372
1373    _filedir -d
1374
1375    if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
1376        i=${COMPREPLY[0]}
1377        if [ "$i" == "$cur" ] && [[ $i != "*/" ]]; then
1378            COMPREPLY[0]="${i}/"
1379        fi
1380    fi
1381
1382    return 0
1383}
1384if shopt -q cdable_vars; then
1385    complete -v -F _cd $nospace cd
1386else
1387    complete -F _cd $nospace cd
1388fi
1389
1390# a wrapper method for the next one, when the offset is unknown
1391_command()
1392{
1393    local offset i
1394
1395    # find actual offset, as position of the first non-option
1396    offset=1
1397    for (( i=1; i <= COMP_CWORD; i++ )); do
1398        if [[ "${COMP_WORDS[i]}" != -* ]]; then
1399            offset=$i
1400            break
1401        fi
1402    done
1403    _command_offset $offset
1404}
1405
1406# A meta-command completion function for commands like sudo(8), which need to
1407# first complete on a command, then complete according to that command's own
1408# completion definition - currently not quite foolproof (e.g. mount and umount
1409# don't work properly), but still quite useful.
1410#
1411_command_offset()
1412{
1413    local cur func cline cspec noglob cmd i char_offset word_offset \
1414    _COMMAND_FUNC _COMMAND_FUNC_ARGS
1415
1416    word_offset=$1
1417
1418    # rewrite current completion context before invoking
1419    # actual command completion
1420
1421    # find new first word position, then
1422    # rewrite COMP_LINE and adjust COMP_POINT
1423    local first_word=${COMP_WORDS[$word_offset]}
1424    for (( i=0; i <= ${#COMP_LINE}; i++ )); do
1425        if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
1426            char_offset=$i
1427            break
1428        fi
1429    done
1430    COMP_LINE=${COMP_LINE:$char_offset}
1431    COMP_POINT=$(( COMP_POINT - $char_offset ))
1432
1433    # shift COMP_WORDS elements and adjust COMP_CWORD
1434    for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
1435        COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
1436    done
1437    for (( i; i <= COMP_CWORD; i++ )); do
1438        unset COMP_WORDS[i];
1439    done
1440    COMP_CWORD=$(( $COMP_CWORD - $word_offset ))
1441
1442    COMPREPLY=()
1443    cur=`_get_cword`
1444
1445    if [[ $COMP_CWORD -eq 0 ]]; then
1446        COMPREPLY=( $( compgen -c -- "$cur" ) )
1447    else
1448        cmd=${COMP_WORDS[0]}
1449        if complete -p $cmd &>/dev/null; then
1450            cspec=$( complete -p $cmd )
1451            if [ "${cspec#* -F }" != "$cspec" ]; then
1452                # complete -F <function>
1453
1454                # get function name
1455                func=${cspec#*-F }
1456                func=${func%% *}
1457
1458                if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
1459                    $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
1460                else
1461                    $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
1462                fi
1463
1464                # remove any \: generated by a command that doesn't
1465                # default to filenames or dirnames (e.g. sudo chown)
1466                # FIXME: I'm pretty sure this does not work!
1467                if [ "${cspec#*-o }" != "$cspec" ]; then
1468                    cspec=${cspec#*-o }
1469                    cspec=${cspec%% *}
1470                    if [[ "$cspec" != @(dir|file)names ]]; then
1471                        COMPREPLY=("${COMPREPLY[@]//\\\\:/:}")
1472                    fi
1473                fi
1474            elif [ -n "$cspec" ]; then
1475                cspec=${cspec#complete};
1476                cspec=${cspec%%$cmd};
1477                COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
1478            fi
1479        fi
1480    fi
1481
1482    [ ${#COMPREPLY[@]} -eq 0 ] && _filedir
1483}
1484complete -F _command $filenames nohup exec nice eval time ltrace then \
1485    else do vsound command xargs tsocks
1486
1487_root_command()
1488{
1489    PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin _command $1 $2 $3
1490}
1491complete -F _root_command $filenames sudo fakeroot really gksudo gksu kdesudo
1492
1493_longopt()
1494{
1495    local cur prev
1496
1497    cur=`_get_cword`
1498    prev=${COMP_WORDS[COMP_CWORD-1]}
1499
1500    if _split_longopt; then
1501        case "$prev" in
1502            *[Dd][Ii][Rr]*)
1503                _filedir -d
1504                ;;
1505            *[Ff][Ii][Ll][Ee]*)
1506                _filedir
1507                ;;
1508        esac
1509        return 0
1510    fi
1511
1512    if [[ "$cur" == -* ]]; then
1513        COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | sed -e '/--/!d' \
1514            -e 's/.*\(--[-A-Za-z0-9]\+\).*/\1/' |sort -u )"\
1515            -- "$cur" ) )
1516    elif [[ "$1" == rmdir ]]; then
1517        _filedir -d
1518    else
1519        _filedir
1520    fi
1521}
1522# makeinfo and texi2dvi are defined elsewhere.
1523for i in a2ps autoconf automake bc gprof ld nm objcopy objdump readelf strip \
1524    bison diff patch enscript cp df dir du ln ls mkfifo mknod mv rm \
1525    touch vdir awk gperf grep grub indent less m4 sed shar date \
1526    tee who texindex cat csplit cut expand fmt fold head \
1527    md5sum nl od paste pr ptx sha1sum sort split tac tail tr unexpand \
1528    uniq wc ldd bash id irb mkdir rmdir; do
1529    have $i && complete -F _longopt $filenames $i
1530done
1531
1532# These commands do not use filenames, so '-o filenames' is not needed.
1533for i in env netstat seq uname units; do
1534    have $i && complete -F _longopt $default $i
1535done
1536unset i
1537
1538# look(1) completion
1539#
1540have look &&
1541_look()
1542{
1543    local cur
1544
1545    COMPREPLY=()
1546    cur=`_get_cword`
1547
1548    if [ $COMP_CWORD = 1 ]; then
1549        COMPREPLY=( $( compgen -W '$(look "$cur" 2>/dev/null)' ) )
1550    fi
1551} &&
1552complete -F _look $default look
1553
1554# id(1) completion
1555#
1556have id &&
1557_id()
1558{
1559    local cur
1560
1561    COMPREPLY=()
1562    cur=`_get_cword`
1563
1564    if [[ "$cur" == -* ]]; then
1565        COMPREPLY=( $( compgen -W '-a -g --group -G --groups -n --name\
1566            -r --real -u --user --help --version' -- "$cur" ) )
1567    else
1568        COMPREPLY=( $( compgen -u "$cur" ) )
1569    fi
1570} &&
1571complete -F _id id
1572
1573_filedir_xspec()
1574{
1575    local IFS cur xspec
1576
1577    IFS=$'\t\n'
1578    COMPREPLY=()
1579    cur=`_get_cword`
1580
1581    _expand || return 0
1582
1583    # get first exclusion compspec that matches this command
1584    xspec=$( sed -ne $'/^complete .*[ \t]'${1##*/}$'\([ \t]\|$\)/{p;q;}' \
1585        $BASH_COMPLETION )
1586    # prune to leave nothing but the -X spec
1587    xspec=${xspec#*-X }
1588    xspec=${xspec%% *}
1589
1590    local -a toks
1591    local tmp
1592
1593    toks=( ${toks[@]-} $(
1594        compgen -d -- "$(quote_readline "$cur")" | {
1595        while read -r tmp; do
1596            # see long TODO comment in _filedir() --David
1597            echo $tmp
1598        done
1599        }
1600        ))
1601
1602    toks=( ${toks[@]-} $(
1603        eval compgen -f -X "$xspec" -- "\$(quote_readline "\$cur")" | {
1604        while read -r tmp; do
1605            [ -n $tmp ] && echo $tmp
1606        done
1607        }
1608        ))
1609
1610    COMPREPLY=( "${toks[@]}" )
1611}
1612list=( $( sed -ne '/^# START exclude/…

Large files files are truncated, but you can click here to view the full file