~ubuntu-branches/ubuntu/trusty/bash-completion/trusty

« back to all changes in this revision

Viewing changes to bash_completion

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2012-07-23 16:07:59 UTC
  • mfrom: (5.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20120723160759-lt9vn33dl3nak9l0
Tags: 1:2.0-1ubuntu1
* debian/maintscript, debian/postinst:
  - clean etc conffiles on upgrade since completion files are in /usr
    with the new version
* Resync with Debian, remaining diff
  * debian/patches/disable-avahi-browse.diff: Disable avahi-browse since
    it scales poorly in the current form: refresh patch
  * patches/101_bash_completion.oga_ogv.patch: Increase support for other
    OGG formats including .oga, .ogx, etc. (LP: #311525)
  * patches/103_colormake.patch: Add support for colormake to the make
    completion rules. (LP: #743208)
* Dropped changes:
  * Add conffile upgrade handling for a run of conffiles that were dropped
    since lucid: lucid upgrades are only supported to precise.
* Those fixes are in the new version
  * debian/patches/apt-get-changelog.patch:
  * Drop whitelists if they fail to produce any results:
  * patches/apt-get-download.patch: Add download as an apt-get
    sub-command (LP: #720541)
  * patches/102_manpager.patch: Override MANPAGER when generating perldoc
    completions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#                                                          -*- shell-script -*-
1
2
#
2
 
#   bash_completion - programmable completion functions for bash 3.2+
 
3
#   bash_completion - programmable completion functions for bash 4.1+
3
4
#
4
5
#   Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
5
6
#             © 2009-2011, Bash Completion Maintainers
17
18
#
18
19
#   You should have received a copy of the GNU General Public License
19
20
#   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
#   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22
#
22
23
#   The latest version of this software can be obtained here:
23
24
#
24
25
#   http://bash-completion.alioth.debian.org/
25
26
#
26
 
#   RELEASE: 1.3
 
27
#   RELEASE: 1.99
27
28
 
28
29
if [[ $- == *v* ]]; then
29
30
    BASH_COMPLETION_ORIGINAL_V_VALUE="-v"
31
32
    BASH_COMPLETION_ORIGINAL_V_VALUE="+v"
32
33
fi
33
34
 
34
 
if [[ -n $BASH_COMPLETION_DEBUG ]]; then
 
35
if [[ ${BASH_COMPLETION_DEBUG-} ]]; then
35
36
    set -v
36
37
else
37
38
    set +v
38
39
fi
39
40
 
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
 
41
# Set the following to the location of the backwards compat completion dir.
 
42
#
 
43
: ${BASH_COMPLETION_COMPAT_DIR:=/etc/bash_completion.d}
 
44
readonly BASH_COMPLETION_COMPAT_DIR
 
45
 
 
46
# Blacklisted completions, causing problems with our code.
 
47
#
 
48
_blacklist_glob='@(acroread.sh)'
57
49
 
58
50
# Turn on extended globbing and programmable completion
59
51
shopt -s extglob progcomp
64
56
# Make directory commands see only directories
65
57
complete -d pushd
66
58
 
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[agmvx]|OG[AGMVX]|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[agmvx]|OG[AGMVX]|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 '!*.@(og[ag]|m3u|flac|spx)' ogg123
101
 
complete -f -X '!*.@(mp3|og[ag]|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
59
# start of section containing compspecs that can be handled within bash
130
60
 
131
61
# user commands see only users
132
 
complete -u su write chfn groups slay w sux runuser
 
62
complete -u write chfn groups slay w sux runuser
133
63
 
134
64
# bg completes with stopped jobs
135
65
complete -A stopped -P '"%' -S '"' bg
163
93
 
164
94
# start of section containing completion functions called by other functions
165
95
 
 
96
# Check if we're running on the given userland
 
97
# @param $1 userland to check for
 
98
_userland()
 
99
{
 
100
    local userland=$( uname -s )
 
101
    [[ $userland == @(Linux|GNU/*) ]] && userland=GNU
 
102
    [[ $userland == $1 ]]
 
103
}
 
104
 
 
105
# This function sets correct SysV init directories
 
106
#
 
107
_sysvdirs()
 
108
{
 
109
    sysvdirs=( )
 
110
    [[ -d /etc/rc.d/init.d ]] && sysvdirs+=( /etc/rc.d/init.d )
 
111
    [[ -d /etc/init.d ]] && sysvdirs+=( /etc/init.d )
 
112
    # Slackware uses /etc/rc.d
 
113
    [[ -f /etc/slackware-version ]] && sysvdirs=( /etc/rc.d )
 
114
}
 
115
 
166
116
# 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
117
#
 
118
_have()
 
119
{
 
120
    # Completions for system administrator commands are installed as well in
 
121
    # case completion is attempted via `sudo command ...'.
 
122
    PATH=$PATH:/usr/sbin:/sbin:/usr/local/sbin type $1 &>/dev/null
 
123
}
 
124
 
 
125
# Backwards compatibility for compat completions that use have().
 
126
# @deprecated should no longer be used; generally not needed with dynamically
 
127
#             loaded completions, and _have is suitable for runtime use.
169
128
have()
170
129
{
171
130
    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"
 
131
    _have $1 && have=yes
176
132
}
177
133
 
178
134
# This function checks whether a given readline variable
186
142
# This function shell-quotes the argument
187
143
quote()
188
144
{
189
 
    echo \'${1//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
 
145
    local quoted=${1//\'/\'\\\'\'}
 
146
    printf "'%s'" "$quoted"
190
147
}
191
148
 
192
149
# @see _quote_readline_by_ref()
201
158
# This function shell-dequotes the argument
202
159
dequote()
203
160
{
204
 
    eval echo "$1" 2> /dev/null
 
161
    eval printf %s "$1" 2> /dev/null
205
162
}
206
163
 
207
164
 
214
171
#       use multiple '_upvar' calls, since one '_upvar' call might
215
172
#       reassign a variable to be used by another '_upvar' call.
216
173
# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
217
 
_upvar() {
 
174
_upvar()
 
175
{
218
176
    if unset -v "$1"; then           # Unset & validate varname
219
177
        if (( $# == 2 )); then
220
178
            eval $1=\"\$2\"          # Return single value
233
191
#     -v   Assign single value to varname
234
192
# Return: 1 if error occurs
235
193
# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
236
 
_upvars() {
 
194
_upvars()
 
195
{
237
196
    if ! (( $# )); then
238
197
        echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
239
198
            "value] | [-aN varname [value ...]] ..." 1>&2
276
235
# @param $2 words  Name of variable to return words to
277
236
# @param $3 cword  Name of variable to return cword to
278
237
#
279
 
__reassemble_comp_words_by_ref() {
280
 
    local exclude i j ref
 
238
__reassemble_comp_words_by_ref()
 
239
{
 
240
    local exclude i j line ref
281
241
    # Exclude word separator characters?
282
242
    if [[ $1 ]]; then
283
243
        # Yes, exclude word separator characters;
290
250
    # Are characters excluded which were former included?
291
251
    if [[ $exclude ]]; then
292
252
        # Yes, list of word completion separators has shrunk;
 
253
        line=$COMP_LINE
293
254
        # Re-assemble words to complete
294
255
        for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
295
256
            # 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
 
257
            # empty and is word made up of just word separator characters to
 
258
            # be excluded and is current word not preceded by whitespace in
 
259
            # original line?
 
260
            while [[ $i -gt 0 && ${COMP_WORDS[$i]} == +([$exclude]) ]]; do
 
261
                # Is word separator not preceded by whitespace in original line
 
262
                # and are we not going to append to word 0 (the command
 
263
                # itself), then append to current word.
 
264
                [[ $line != [$' \t']* ]] && (( j >= 2 )) && ((j--))
 
265
                # Append word separator to current or new word
303
266
                ref="$2[$j]"
304
267
                eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
305
268
                # Indicate new cword
306
 
                [ $i = $COMP_CWORD ] && eval $3=$j
307
 
                # Indicate next word if available, else end *both* while and for loop
 
269
                [[ $i == $COMP_CWORD ]] && eval $3=$j
 
270
                # Remove optional whitespace + word separator from line copy
 
271
                line=${line#*"${COMP_WORDS[$i]}"}
 
272
                # Start new word if word separator in original line is
 
273
                # followed by whitespace.
 
274
                [[ $line == [$' \t']* ]] && ((j++))
 
275
                # Indicate next word if available, else end *both* while and
 
276
                # for loop
308
277
                (( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
309
278
            done
310
279
            # Append word to current word
311
280
            ref="$2[$j]"
312
281
            eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
 
282
            # Remove optional whitespace + word from line copy
 
283
            line=${line#*"${COMP_WORDS[i]}"}
313
284
            # Indicate new cword
314
285
            [[ $i == $COMP_CWORD ]] && eval $3=$j
315
286
        done
323
294
# @param $1 exclude  Characters out of $COMP_WORDBREAKS which should NOT be
324
295
#     considered word breaks. This is useful for things like scp where
325
296
#     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.
 
297
#     colon (:) as $1 in this case.
328
298
# @param $2 words  Name of variable to return words to
329
299
# @param $3 cword  Name of variable to return cword to
330
300
# @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() {
 
301
# @see __reassemble_comp_words_by_ref()
 
302
__get_cword_at_cursor_by_ref()
 
303
{
333
304
    local cword words=()
334
305
    __reassemble_comp_words_by_ref "$1" words cword
335
306
 
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--))
 
307
    local i cur index=$COMP_POINT lead=${COMP_LINE:0:$COMP_POINT}
 
308
    # Cursor not at position 0 and not leaded by just space(s)?
 
309
    if [[ $index -gt 0 && ( $lead && ${lead//[[:space:]]} ) ]]; then
 
310
        cur=$COMP_LINE
 
311
        for (( i = 0; i <= cword; ++i )); do
 
312
            while [[
 
313
                # Current word fits in $cur?
 
314
                ${#cur} -ge ${#words[i]} &&
 
315
                # $cur doesn't match cword?
 
316
                "${cur:0:${#words[i]}}" != "${words[i]}"
 
317
            ]]; do
 
318
                # Strip first character
 
319
                cur="${cur:1}"
 
320
                # Decrease cursor position
 
321
                ((index--))
 
322
            done
 
323
 
 
324
            # Does found word match cword?
 
325
            if [[ $i -lt $cword ]]; then
 
326
                # No, cword lies further;
 
327
                local old_size=${#cur}
 
328
                cur="${cur#"${words[i]}"}"
 
329
                local new_size=${#cur}
 
330
                index=$(( index - old_size + new_size ))
 
331
            fi
350
332
        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}
 
333
        # Clear $cur if just space(s)
 
334
        [[ $cur && ! ${cur//[[:space:]]} ]] && cur=
 
335
        # Zero $index if negative
 
336
        [[ $index -lt 0 ]] && index=0
367
337
    fi
368
338
 
369
 
    local "$2" "$3" "$4" && 
370
 
        _upvars -a${#words[@]} $2 "${words[@]}" -v $3 "$cword" -v $4 "$cur2"
 
339
    local "$2" "$3" "$4" && _upvars -a${#words[@]} $2 "${words[@]}" \
 
340
        -v $3 "$cword" -v $4 "${cur:0:$index}"
371
341
}
372
342
 
373
343
 
388
358
#     -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT be 
389
359
#                 considered word breaks. This is useful for things like scp
390
360
#                 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.
 
361
#                 would pass the colon (:) as -n option in this case.
394
362
#     -c VARNAME  Return cur via $VARNAME
395
363
#     -p VARNAME  Return prev via $VARNAME
396
364
#     -w VARNAME  Return words via $VARNAME
431
399
 
432
400
    [[ $vcur   ]] && { upvars+=("$vcur"  ); upargs+=(-v $vcur   "$cur"  ); }
433
401
    [[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
434
 
    [[ $vprev  ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev 
 
402
    [[ $vprev && $cword -ge 1 ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev 
435
403
        "${words[cword - 1]}"); }
436
404
    [[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
437
405
        "${words[@]}"); }
448
416
# @param $1 string  Characters out of $COMP_WORDBREAKS which should NOT be
449
417
#     considered word breaks. This is useful for things like scp where
450
418
#     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.
 
419
#     colon (:) as $1 in this case.
453
420
# @param $2 integer  Index number of word to return, negatively offset to the
454
421
#     current word (default is 0, previous is 1), respecting the exclusions
455
422
#     given at $1.  For example, `_get_cword "=:" 1' returns the word left of
514
481
#
515
482
_get_pword() 
516
483
{
517
 
    if [ $COMP_CWORD -ge 1 ]; then
518
 
        _get_cword "${@:-}" 1;
 
484
    if [[ $COMP_CWORD -ge 1 ]]; then
 
485
        _get_cword "${@:-}" 1
519
486
    fi
520
487
}
521
488
 
522
489
 
523
490
# If the word-to-complete contains a colon (:), left-trim COMPREPLY items with
524
491
# word-to-complete.
525
 
# On bash-3, and bash-4 with a colon in COMP_WORDBREAKS, words containing
 
492
# With a colon in COMP_WORDBREAKS, words containing
526
493
# colons are always completed as entire words if the word to complete contains
527
494
# a colon.  This function fixes this, by removing the colon-containing-prefix
528
495
# from COMPREPLY items.
537
504
# @param $1 current word to complete (cur)
538
505
# @modifies global array $COMPREPLY
539
506
#
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
 
507
__ltrim_colon_completions()
 
508
{
 
509
    if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
550
510
        # Remove colon-word prefix from COMPREPLY items
551
511
        local colon_word=${1%${1##*:}}
552
512
        local i=${#COMPREPLY[*]}
553
 
        while [ $((--i)) -ge 0 ]; do
 
513
        while [[ $((--i)) -ge 0 ]]; do
554
514
            COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
555
515
        done
556
516
    fi
564
524
#     $ ls "a'b/"
565
525
#     c
566
526
#     $ 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
 
527
#     $ compgen -f "a\'b/"      # Good
 
528
#     a\'b/c
581
529
#
582
530
# See also:
583
531
# - http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
587
535
# @param $2  Name of variable to return result to
588
536
_quote_readline_by_ref()
589
537
{
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}"
 
538
    if [[ $1 == \'* ]]; then
 
539
        # Leave out first character
 
540
        printf -v $2 %s "${1:1}"
602
541
    else
603
542
        printf -v $2 %q "$1"
604
543
    fi
606
545
    # If result becomes quoted like this: $'string', re-evaluate in order to
607
546
    # drop the additional quoting.  See also: http://www.mail-archive.com/
608
547
    # bash-completion-devel@lists.alioth.debian.org/msg01942.html
609
 
    [[ ${!2:0:1} == '$' ]] && eval $2=${!2}
 
548
    [[ ${!2} == \$* ]] && eval $2=${!2}
610
549
} # _quote_readline_by_ref()
611
550
 
612
551
 
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
552
# This function performs file and directory completion. It's better than
627
553
# simply using 'compgen -f', because it honours spaces in filenames.
628
554
# @param $1  If `-d', complete only on directories.  Otherwise filter/pick only
636
562
    _tilde "$cur" || return 0
637
563
 
638
564
    local -a toks
639
 
    local quoted tmp
 
565
    local quoted x tmp
640
566
 
641
567
    _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
 
    ))
 
568
    x=$( compgen -d -- "$quoted" ) &&
 
569
    while read -r tmp; do
 
570
        toks+=( "$tmp" )
 
571
    done <<< "$x"
654
572
 
655
573
    if [[ "$1" != -d ]]; then
656
574
        # 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[@]}" )
 
575
        # http://thread.gmane.org/gmane.comp.shells.bash.bugs/15294/focus=15306
 
576
        xspec=${1:+"!*.@($1|${1^^})"}
 
577
        x=$( compgen -f -X "$xspec" -- $quoted ) &&
 
578
        while read -r tmp; do
 
579
            toks+=( "$tmp" )
 
580
        done <<< "$x"
 
581
    fi
 
582
 
 
583
    # If the filter failed to produce anything, try without it if configured to
 
584
    [[ -n ${COMP_FILEDIR_FALLBACK:-} && \
 
585
        -n "$1" && "$1" != -d && ${#toks[@]} -lt 1 ]] && \
 
586
        x=$( compgen -f -- $quoted ) &&
 
587
        while read -r tmp; do
 
588
            toks+=( "$tmp" )
 
589
        done <<< "$x"
 
590
 
 
591
 
 
592
    if [[ ${#toks[@]} -ne 0 ]]; then
 
593
        # 2>/dev/null for direct invocation, e.g. in the _filedir unit test
 
594
        compopt -o filenames 2>/dev/null
 
595
        COMPREPLY+=( "${toks[@]}" )
 
596
    fi
670
597
} # _filedir()
671
598
 
672
599
 
673
600
# This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it
674
601
# easier to support both "--foo bar" and "--foo=bar" style completions.
 
602
# `=' should have been removed from COMP_WORDBREAKS when setting $cur for
 
603
# this to be useful.
675
604
# Returns 0 if current option was split, 1 otherwise.
676
605
#
677
606
_split_longopt()
687
616
    return 1
688
617
}
689
618
 
690
 
# This function tries to parse the help output of the given command.
691
 
# @param $1  command
 
619
# Complete variables.
 
620
# @return  True (0) if variables were completed, 
 
621
#          False (> 0) if not.
 
622
_variables()
 
623
{
 
624
    if [[ $cur =~ ^(\$\{?)([A-Za-z0-9_]*)$ ]]; then
 
625
        [[ $cur == *{* ]] && local suffix=} || local suffix=
 
626
        COMPREPLY+=( $( compgen -P ${BASH_REMATCH[1]} -S "$suffix" -v -- \
 
627
            "${BASH_REMATCH[2]}" ) )
 
628
        return 0
 
629
    fi
 
630
    return 1
 
631
}
 
632
 
 
633
# Initialize completion and deal with various general things: do file
 
634
# and variable completion where appropriate, and adjust prev, words,
 
635
# and cword as if no redirections exist so that completions do not
 
636
# need to deal with them.  Before calling this function, make sure
 
637
# cur, prev, words, and cword are local, ditto split if you use -s.
 
638
#
 
639
# Options:
 
640
#     -n EXCLUDE  Passed to _get_comp_words_by_ref -n with redirection chars
 
641
#     -e XSPEC    Passed to _filedir as first arg for stderr redirections
 
642
#     -o XSPEC    Passed to _filedir as first arg for other output redirections
 
643
#     -i XSPEC    Passed to _filedir as first arg for stdin redirections
 
644
#     -s          Split long options with _split_longopt, implies -n =
 
645
# @return  True (0) if completion needs further processing, 
 
646
#          False (> 0) no further processing is necessary.
 
647
#
 
648
_init_completion()
 
649
{
 
650
    local exclude= flag outx errx inx OPTIND=1
 
651
 
 
652
    while getopts "n:e:o:i:s" flag "$@"; do
 
653
        case $flag in
 
654
            n) exclude+=$OPTARG ;;
 
655
            e) errx=$OPTARG ;;
 
656
            o) outx=$OPTARG ;;
 
657
            i) inx=$OPTARG ;;
 
658
            s) split=false ; exclude+== ;;
 
659
        esac
 
660
    done
 
661
 
 
662
    # For some reason completion functions are not invoked at all by
 
663
    # bash (at least as of 4.1.7) after the command line contains an
 
664
    # ampersand so we don't get a chance to deal with redirections
 
665
    # containing them, but if we did, hopefully the below would also
 
666
    # do the right thing with them...
 
667
 
 
668
    COMPREPLY=()
 
669
    local redir="@(?([0-9])<|?([0-9&])>?(>)|>&)"
 
670
    _get_comp_words_by_ref -n "$exclude<>&" cur prev words cword
 
671
 
 
672
    # Complete variable names.
 
673
    _variables && return 1
 
674
 
 
675
    # Complete on files if current is a redirect possibly followed by a
 
676
    # filename, e.g. ">foo", or previous is a "bare" redirect, e.g. ">".
 
677
    if [[ $cur == $redir* || $prev == $redir ]]; then
 
678
        local xspec
 
679
        case $cur in
 
680
            2'>'*) xspec=$errx ;;
 
681
            *'>'*) xspec=$outx ;;
 
682
            *'<'*) xspec=$inx ;;
 
683
            *)
 
684
                case $prev in
 
685
                    2'>'*) xspec=$errx ;;
 
686
                    *'>'*) xspec=$outx ;;
 
687
                    *'<'*) xspec=$inx ;;
 
688
                esac
 
689
                ;;
 
690
        esac
 
691
        cur="${cur##$redir}"
 
692
        _filedir $xspec
 
693
        return 1
 
694
    fi
 
695
 
 
696
    # Remove all redirections so completions don't have to deal with them.
 
697
    local i skip
 
698
    for (( i=1; i < ${#words[@]}; )); do
 
699
        if [[ ${words[i]} == $redir* ]]; then
 
700
            # If "bare" redirect, remove also the next word (skip=2).
 
701
            [[ ${words[i]} == $redir ]] && skip=2 || skip=1
 
702
            words=( "${words[@]:0:i}" "${words[@]:i+skip}" )
 
703
            [[ $i -le $cword ]] && cword=$(( cword - skip ))
 
704
        else
 
705
            i=$(( ++i ))
 
706
        fi
 
707
    done
 
708
 
 
709
    [[ $cword -eq 0 ]] && return 1
 
710
    prev=${words[cword-1]}
 
711
 
 
712
    [[ ${split-} ]] && _split_longopt && split=true
 
713
 
 
714
    return 0
 
715
}
 
716
 
 
717
# Helper function for _parse_help and _parse_usage.
 
718
__parse_options()
 
719
{
 
720
    local option option2 i IFS=$' \t\n,/|'
 
721
 
 
722
    # Take first found long option, or first one (short) if not found.
 
723
    option=
 
724
    for i in $1; do
 
725
        case $i in
 
726
            ---*) break ;;
 
727
            --?*) option=$i ; break ;;
 
728
            -?*)  [[ $option ]] || option=$i ;;
 
729
            *)    break ;;
 
730
        esac
 
731
    done
 
732
    [[ $option ]] || return 0
 
733
 
 
734
    IFS=$' \t\n' # affects parsing of the regexps below...
 
735
 
 
736
    # Expand --[no]foo to --foo and --nofoo etc
 
737
    if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
 
738
        option2=${option/"${BASH_REMATCH[1]}"/}
 
739
        option2=${option2%%[<{().[]*}
 
740
        printf '%s\n' "${option2/=*/=}"
 
741
        option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"}
 
742
    fi
 
743
 
 
744
    option=${option%%[<{().[]*}
 
745
    printf '%s\n' "${option/=*/=}"
 
746
}
 
747
 
 
748
# Parse GNU style help output of the given command.
 
749
# @param $1  command; if "-", read from stdin and ignore rest of args
692
750
# @param $2  command options (default: --help)
693
751
#
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|[<=].*||'
 
752
_parse_help()
 
753
{
 
754
    eval local cmd=$( quote "$1" )
 
755
    local line
 
756
    { case $cmd in
 
757
        -) cat ;;
 
758
        *) "$( dequote "$cmd" )" ${2:---help} 2>&1 ;;
 
759
      esac } \
 
760
    | while read -r line; do
 
761
 
 
762
        [[ $line == *([ $'\t'])-* ]] || continue
 
763
        # transform "-f FOO, --foo=FOO" to "-f , --foo=FOO" etc
 
764
        while [[ $line =~ \
 
765
            ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+\]? ]]; do
 
766
            line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"}
 
767
        done
 
768
        __parse_options "${line// or /, }"
 
769
 
 
770
    done
697
771
}
698
772
 
699
 
# This function completes on signal names
 
773
# Parse BSD style usage output (options in brackets) of the given command.
 
774
# @param $1  command; if "-", read from stdin and ignore rest of args
 
775
# @param $2  command options (default: --usage)
700
776
#
 
777
_parse_usage()
 
778
{
 
779
    eval local cmd=$( quote "$1" )
 
780
    local line match option i char
 
781
    { case $cmd in
 
782
        -) cat ;;
 
783
        *) "$( dequote "$cmd" )" ${2:---usage} 2>&1 ;;
 
784
      esac } \
 
785
    | while read -r line; do
 
786
 
 
787
        while [[ $line =~ \[[[:space:]]*(-[^]]+)[[:space:]]*\] ]]; do
 
788
            match=${BASH_REMATCH[0]}
 
789
            option=${BASH_REMATCH[1]}
 
790
            case $option in
 
791
                -?(\[)+([a-zA-Z0-9?]))
 
792
                    # Treat as bundled short options
 
793
                    for (( i=1; i < ${#option}; i++ )); do
 
794
                        char=${option:i:1}
 
795
                        [[ $char != '[' ]] && printf '%s\n' -$char
 
796
                    done
 
797
                    ;;
 
798
                *)
 
799
                    __parse_options "$option"
 
800
                    ;;
 
801
            esac
 
802
            line=${line#*"$match"}
 
803
        done
 
804
 
 
805
    done
 
806
}
 
807
 
 
808
# This function completes on signal names (minus the SIG prefix)
 
809
# @param $1 prefix
701
810
_signals()
702
811
{
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
 
812
    local -a sigs=( $( compgen -P "$1" -A signal "SIG${cur#$1}" ) )
 
813
    COMPREPLY+=( "${sigs[@]/#${1}SIG/${1}}" )
713
814
}
714
815
 
715
816
# This function completes on known mac addresses
719
820
    local re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}'
720
821
    local PATH="$PATH:/sbin:/usr/sbin"
721
822
 
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" ) )
 
823
    # Local interfaces (Linux: HWAddr, FreeBSD: ether)
 
824
    COMPREPLY+=( $( ifconfig -a 2>/dev/null | sed -ne \
 
825
        "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" -ne \
 
826
        "s/^[[:space:]]\{1,\}ether[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" \
 
827
        ) )
725
828
 
726
829
    # ARP cache
727
 
    COMPREPLY=( "${COMPREPLY[@]}" $( arp -an 2>/dev/null | sed -ne \
 
830
    COMPREPLY+=( $( arp -an 2>/dev/null | sed -ne \
728
831
        "s/.*[[:space:]]\($re\)[[:space:]].*/\1/p" -ne \
729
832
        "s/.*[[:space:]]\($re\)[[:space:]]*$/\1/p" ) )
730
833
 
731
834
    # /etc/ethers
732
 
    COMPREPLY=( "${COMPREPLY[@]}" $( sed -ne \
 
835
    COMPREPLY+=( $( sed -ne \
733
836
        "s/^[[:space:]]*\($re\)[[:space:]].*/\1/p" /etc/ethers 2>/dev/null ) )
734
837
 
735
838
    COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) )
740
843
#
741
844
_configured_interfaces()
742
845
{
743
 
    if [ -f /etc/debian_version ]; then
 
846
    if [[ -f /etc/debian_version ]]; then
744
847
        # Debian system
745
848
        COMPREPLY=( $( compgen -W "$( sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p'\
746
849
            /etc/network/interfaces )" -- "$cur" ) )
747
 
    elif [ -f /etc/SuSE-release ]; then
 
850
    elif [[ -f /etc/SuSE-release ]]; then
748
851
        # SuSE system
749
852
        COMPREPLY=( $( compgen -W "$( printf '%s\n' \
750
853
            /etc/sysconfig/network/ifcfg-* | \
751
854
            sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
752
 
    elif [ -f /etc/pld-release ]; then
 
855
    elif [[ -f /etc/pld-release ]]; then
753
856
        # PLD Linux
754
857
        COMPREPLY=( $( compgen -W "$( command ls -B \
755
858
            /etc/sysconfig/interfaces | \
762
865
    fi
763
866
}
764
867
 
 
868
# Local IP addresses.
 
869
#
 
870
_ip_addresses()
 
871
{
 
872
    COMPREPLY+=( $( compgen -W \
 
873
        "$( PATH="$PATH:/sbin" LC_ALL=C ifconfig -a |
 
874
            sed -ne 's/.*addr:\([^[:space:]]*\).*/\1/p' \
 
875
                -ne 's/.*inet[[:space:]]\{1,\}\([^[:space:]]*\).*/\1/p' )" \
 
876
        -- "$cur" ) )
 
877
}
 
878
 
765
879
# This function completes on available kernels
766
880
#
767
881
_kernel_versions()
777
891
{
778
892
    local cmd
779
893
 
780
 
    if [ "${1:-}" = -w ]; then
 
894
    if [[ ${1:-} == -w ]]; then
781
895
        cmd="iwconfig"
782
 
    elif [ "${1:-}" = -a ]; then
 
896
    elif [[ ${1:-} == -a ]]; then
783
897
        cmd="ifconfig"
784
898
    else
785
899
        cmd="ifconfig -a"
790
904
    COMPREPLY=( $( compgen -W '${COMPREPLY[@]/%[[:punct:]]/}' -- "$cur" ) )
791
905
}
792
906
 
 
907
# Echo number of CPUs, falling back to 1 on failure.
 
908
_ncpus()
 
909
{
 
910
    local var=NPROCESSORS_ONLN
 
911
    [[ $OSTYPE == *linux* ]] && var=_$var
 
912
    local n=$( getconf $var 2>/dev/null )
 
913
    printf %s ${n:-1}
 
914
}
793
915
 
794
916
# Perform tilde (~) completion
795
917
# @return  True (0) if completion needs further processing, 
796
918
#          False (> 0) if tilde is followed by a valid username, completions
797
919
#          are put in COMPREPLY and no further processing is necessary.
798
 
_tilde() {
 
920
_tilde()
 
921
{
799
922
    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
 
923
    if [[ $1 == \~* && $1 != */* ]]; then
 
924
        # Try generate ~username completions
804
925
        COMPREPLY=( $( compgen -P '~' -u "${1#\~}" ) )
805
926
        result=${#COMPREPLY[@]}
 
927
        # 2>/dev/null for direct invocation, e.g. in the _tilde unit test
 
928
        [[ $result -gt 0 ]] && compopt -o filenames 2>/dev/null
806
929
    fi
807
930
    return $result
808
931
}
830
953
#    ~foo/*           /home/foo/*
831
954
#  
832
955
# @param $1  Name of variable (not the value of the variable) to expand
833
 
__expand_tilde_by_ref() {
 
956
__expand_tilde_by_ref()
 
957
{
834
958
    # Does $1 start with tilde (~)?
835
 
    if [ "${!1:0:1}" = "~" ]; then
 
959
    if [[ ${!1} == \~* ]]; then
836
960
        # Does $1 contain slash (/)?
837
 
        if [ "${!1}" != "${!1//\/}" ]; then
 
961
        if [[ ${!1} == */* ]]; then
838
962
            # Yes, $1 contains slash;
839
963
            # 1: Remove * including and after first slash (/), i.e. "~a/b"
840
964
            #    becomes "~a".  Double quotes allow eval.
855
979
_expand()
856
980
{
857
981
    # FIXME: Why was this here?
858
 
    #[ "$cur" != "${cur%\\}" ] && cur="$cur\\"
 
982
    #[ "$cur" != "${cur%\\}" ] && cur+="\\"
859
983
 
860
984
    # Expand ~username type directory specifications.  We want to expand
861
985
    # ~foo/... to /home/foo/... to avoid problems when $cur starting with
862
986
    # a tilde is fed to commands and ending up quoted instead of expanded.
863
987
 
864
988
    if [[ "$cur" == \~*/* ]]; then
865
 
        eval cur=$cur
 
989
        eval cur=$cur 2>/dev/null
866
990
    elif [[ "$cur" == \~* ]]; then
867
991
        cur=${cur#\~}
868
992
        COMPREPLY=( $( compgen -P '~' -u "$cur" ) )
869
 
        [ ${#COMPREPLY[@]} -eq 1 ] && eval COMPREPLY[0]=${COMPREPLY[0]}
 
993
        [[ ${#COMPREPLY[@]} -eq 1 ]] && eval COMPREPLY[0]=${COMPREPLY[0]}
870
994
        return ${#COMPREPLY[@]}
871
995
    fi
872
996
}
873
997
 
874
998
# This function completes on process IDs.
875
999
# AIX and Solaris ps prefers X/Open syntax.
876
 
[[ $UNAME == SunOS || $UNAME == AIX ]] &&
 
1000
[[ $OSTYPE == *@(solaris|aix)* ]] &&
877
1001
_pids()
878
1002
{
879
1003
    COMPREPLY=( $( compgen -W '$( command ps -efo pid | sed 1d )' -- "$cur" ))
885
1009
 
886
1010
# This function completes on process group IDs.
887
1011
# AIX and SunOS prefer X/Open, all else should be BSD.
888
 
[[ $UNAME == SunOS || $UNAME == AIX ]] &&
 
1012
[[ $OSTYPE == *@(solaris|aix)* ]] &&
889
1013
_pgids()
890
1014
{
891
1015
    COMPREPLY=( $( compgen -W '$( command ps -efo pgid | sed 1d )' -- "$cur" ))
897
1021
 
898
1022
# This function completes on process names.
899
1023
# AIX and SunOS prefer X/Open, all else should be BSD.
900
 
[[ $UNAME == SunOS || $UNAME == AIX ]] &&
 
1024
[[ $OSTYPE == *@(solaris|aix)* ]] &&
901
1025
_pnames()
902
1026
{
903
1027
    COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps -efo comm | \
947
1071
    fi
948
1072
}
949
1073
 
 
1074
# Glob for matching various backup files.
 
1075
#
 
1076
_backup_glob='@(#*#|*@(~|.@(bak|orig|rej|swp|dpkg*|rpm@(orig|new|save))))'
 
1077
 
 
1078
# Complete on xinetd services
 
1079
#
 
1080
_xinetd_services()
 
1081
{
 
1082
    local xinetddir=/etc/xinetd.d
 
1083
    if [[ -d $xinetddir ]]; then
 
1084
        local restore_nullglob=$(shopt -p nullglob); shopt -s nullglob
 
1085
        local -a svcs=( $( printf '%s\n' $xinetddir/!($_backup_glob) ) )
 
1086
        $restore_nullglob
 
1087
        COMPREPLY+=( $( compgen -W '${svcs[@]#$xinetddir/}' -- "$cur" ) )
 
1088
    fi
 
1089
}
 
1090
 
950
1091
# This function completes on services
951
1092
#
952
1093
_services()
953
1094
{
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)|*~) ) )
 
1095
    local sysvdirs
 
1096
    _sysvdirs
 
1097
 
 
1098
    local restore_nullglob=$(shopt -p nullglob); shopt -s nullglob
 
1099
    COMPREPLY=( $( printf '%s\n' ${sysvdirs[0]}/!($_backup_glob|functions) ) )
 
1100
    $restore_nullglob
 
1101
 
 
1102
    COMPREPLY+=( $( systemctl list-units --full --all 2>/dev/null | \
 
1103
        awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }' ) )
 
1104
 
 
1105
    COMPREPLY=( $( compgen -W '${COMPREPLY[@]#${sysvdirs[0]}/}' -- "$cur" ) )
 
1106
}
 
1107
 
 
1108
# This completes on a list of all available service scripts for the
 
1109
# 'service' command and/or the SysV init.d directory, followed by
 
1110
# that script's available commands
 
1111
#
 
1112
_service()
 
1113
{
 
1114
    local cur prev words cword
 
1115
    _init_completion || return
 
1116
 
 
1117
    # don't complete past 2nd token
 
1118
    [[ $cword -gt 2 ]] && return 0
 
1119
 
 
1120
    if [[ $cword -eq 1 && $prev == ?(*/)service ]]; then
 
1121
        _services
 
1122
        [[ -e /etc/mandrake-release ]] && _xinetd_services
 
1123
    else
 
1124
        local sysvdirs
 
1125
        _sysvdirs
 
1126
        COMPREPLY=( $( compgen -W '`sed -e "y/|/ /" \
 
1127
            -ne "s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \
 
1128
            ${sysvdirs[0]}/${prev##*/} 2>/dev/null` start stop' -- "$cur" ) )
963
1129
    fi
964
 
 
965
 
    COMPREPLY=( $( compgen -W '${COMPREPLY[@]#@($sysvdir|$famdir)/}' -- "$cur" ) )
966
 
}
 
1130
} &&
 
1131
complete -F _service service
 
1132
_sysvdirs
 
1133
for svcdir in ${sysvdirs[@]}; do
 
1134
    for svc in $svcdir/!($_backup_glob); do
 
1135
        [[ -x $svc ]] && complete -F _service $svc
 
1136
    done
 
1137
done
 
1138
unset svc svcdir sysvdirs
967
1139
 
968
1140
# This function completes on modules
969
1141
#
971
1143
{
972
1144
    local modpath
973
1145
    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" ) )
 
1146
    COMPREPLY=( $( compgen -W "$( command ls -RL $modpath 2>/dev/null | \
 
1147
        sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.[gx]z\)\{0,1\}$/\1/p' )" -- "$cur" ) )
976
1148
}
977
1149
 
978
1150
# This function completes on installed modules
1064
1236
#
1065
1237
_shells()
1066
1238
{
1067
 
    COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W \
1068
 
        '$( command grep "^[[:space:]]*/" /etc/shells 2>/dev/null )' \
1069
 
        -- "$cur" ) )
 
1239
    local shell rest
 
1240
    while read -r shell rest; do
 
1241
        [[ $shell == /* && $shell == "$cur"* ]] && COMPREPLY+=( $shell )
 
1242
    done 2>/dev/null < /etc/shells
1070
1243
}
1071
1244
 
1072
1245
# This function completes on valid filesystem types
1075
1248
{
1076
1249
    local fss
1077
1250
 
1078
 
    if [ -e /proc/filesystems ] ; then
 
1251
    if [[ -e /proc/filesystems ]]; then
1079
1252
        # Linux
1080
1253
        fss="$( cut -d$'\t' -f2 /proc/filesystems )
1081
1254
             $( awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null )"
1085
1258
             $( awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null )
1086
1259
             $( awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null )
1087
1260
             $( awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null )
1088
 
             $( [ -d /etc/fs ] && command ls /etc/fs )"
 
1261
             $( [[ -d /etc/fs ]] && command ls /etc/fs )"
1089
1262
    fi
1090
1263
 
1091
 
    [ -n "$fss" ] && \
1092
 
        COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$fss" -- "$cur" ) )
 
1264
    [[ -n $fss ]] && COMPREPLY+=( $( compgen -W "$fss" -- "$cur" ) )
1093
1265
}
1094
1266
 
1095
1267
# Get real command.
1102
1274
    type -P "$1" > /dev/null && {
1103
1275
        if type -p realpath > /dev/null; then
1104
1276
            realpath "$(type -P "$1")"
 
1277
        elif type -p greadlink > /dev/null; then
 
1278
            greadlink -f "$(type -P "$1")"
1105
1279
        elif type -p readlink > /dev/null; then
1106
1280
            readlink -f "$(type -P "$1")"
1107
1281
        else
1110
1284
    }
1111
1285
}
1112
1286
 
1113
 
# This function returns the first arugment, excluding options
 
1287
# This function returns the first argument, excluding options
1114
1288
# @param $1 chars  Characters out of $COMP_WORDBREAKS which should
1115
1289
#     NOT be considered word breaks. See __reassemble_comp_words_by_ref.
1116
1290
_get_first_arg()
1145
1319
#
1146
1320
_pci_ids()
1147
1321
{
1148
 
    COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
 
1322
    COMPREPLY+=( $( compgen -W \
1149
1323
        "$( PATH="$PATH:/sbin" lspci -n | awk '{print $3}')" -- "$cur" ) )
1150
1324
}
1151
1325
 
1153
1327
#
1154
1328
_usb_ids()
1155
1329
{
1156
 
    COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
 
1330
    COMPREPLY+=( $( compgen -W \
1157
1331
        "$( PATH="$PATH:/sbin" lsusb | awk '{print $6}' )" -- "$cur" ) )
1158
1332
}
1159
1333
 
1160
1334
# CD device names
1161
1335
_cd_devices()
1162
1336
{
1163
 
    COMPREPLY=( "${COMPREPLY[@]}"
1164
 
        $( compgen -f -d -X "!*/?([amrs])cd*" -- "${cur:-/dev/}" ) )
 
1337
    COMPREPLY+=( $( compgen -f -d -X "!*/?([amrs])cd*" -- "${cur:-/dev/}" ) )
1165
1338
}
1166
1339
 
1167
1340
# DVD device names
1168
1341
_dvd_devices()
1169
1342
{
1170
 
    COMPREPLY=( "${COMPREPLY[@]}"
1171
 
        $( compgen -f -d -X "!*/?(r)dvd*" -- "${cur:-/dev/}" ) )
 
1343
    COMPREPLY+=( $( compgen -f -d -X "!*/?(r)dvd*" -- "${cur:-/dev/}" ) )
1172
1344
}
1173
1345
 
1174
 
# start of section containing completion functions for external programs
 
1346
# TERM environment variable values
 
1347
_terms()
 
1348
{
 
1349
    COMPREPLY+=( $( compgen -W \
 
1350
        "$( sed -ne 's/^\([^[:space:]#|]\{2,\}\)|.*/\1/p' /etc/termcap \
 
1351
            2>/dev/null )" -- "$cur" ) )
 
1352
    COMPREPLY+=( $( compgen -W "$( { toe -a 2>/dev/null || toe 2>/dev/null; } \
 
1353
        | awk '{ print $1 }' | sort -u )" -- "$cur" ) )
 
1354
}
1175
1355
 
1176
1356
# 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
 
1357
[[ $OSTYPE == *freebsd* ]] && complete -W 'index search fetch fetch-list
 
1358
    extract patch configure build install reinstall deinstall clean
 
1359
    clean-depends kernel buildworld' make
1180
1360
 
1181
1361
# This function provides simple user@host completion
1182
1362
#
1183
 
_user_at_host() {
1184
 
    local cur
1185
 
 
1186
 
    COMPREPLY=()
1187
 
    _get_comp_words_by_ref -n : cur
 
1363
_user_at_host()
 
1364
{
 
1365
    local cur prev words cword
 
1366
    _init_completion -n : || return
1188
1367
 
1189
1368
    if [[ $cur == *@* ]]; then
1190
1369
        _known_hosts_real "$cur"
1200
1379
#       `_known_hosts_real' instead.
1201
1380
_known_hosts()
1202
1381
{
1203
 
    local options
1204
 
    COMPREPLY=()
 
1382
    local cur prev words cword
 
1383
    _init_completion -n : || return
1205
1384
 
1206
1385
    # NOTE: Using `_known_hosts' as a helper function and passing options
1207
1386
    #       to `_known_hosts' is deprecated: Use `_known_hosts_real' instead.
 
1387
    local options
1208
1388
    [[ "$1" == -a || "$2" == -a ]] && options=-a
1209
 
    [[ "$1" == -c || "$2" == -c ]] && options="$options -c"
1210
 
    _known_hosts_real $options "$(_get_cword :)"
 
1389
    [[ "$1" == -c || "$2" == -c ]] && options+=" -c"
 
1390
    _known_hosts_real $options -- "$cur"
1211
1391
} # _known_hosts()
1212
1392
 
1213
1393
# Helper function for completing _known_hosts.
1237
1417
            p) prefix=$OPTARG ;;
1238
1418
        esac
1239
1419
    done
1240
 
    [ $# -lt $OPTIND ] && echo "error: $FUNCNAME: missing mandatory argument CWORD"
 
1420
    [[ $# -lt $OPTIND ]] && echo "error: $FUNCNAME: missing mandatory argument CWORD"
1241
1421
    cur=${!OPTIND}; let "OPTIND += 1"
1242
 
    [ $# -ge $OPTIND ] && echo "error: $FUNCNAME("$@"): unprocessed arguments:"\
1243
 
    $(while [ $# -ge $OPTIND ]; do printf '%s\n' ${!OPTIND}; shift; done)
 
1422
    [[ $# -ge $OPTIND ]] && echo "error: $FUNCNAME("$@"): unprocessed arguments:"\
 
1423
    $(while [[ $# -ge $OPTIND ]]; do printf '%s\n' ${!OPTIND}; shift; done)
1244
1424
 
1245
1425
    [[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
1246
1426
    kh=()
1247
1427
 
1248
1428
    # ssh config files
1249
 
    if [ -n "$configfile" ]; then
1250
 
        [ -r "$configfile" ] &&
1251
 
        config=( "${config[@]}" "$configfile" )
 
1429
    if [[ -n $configfile ]]; then
 
1430
        [[ -r $configfile ]] && config+=( "$configfile" )
1252
1431
    else
1253
 
        for i in /etc/ssh/ssh_config "${HOME}/.ssh/config" \
1254
 
            "${HOME}/.ssh2/config"; do
1255
 
            [ -r $i ] && config=( "${config[@]}" "$i" )
 
1432
        for i in /etc/ssh/ssh_config ~/.ssh/config ~/.ssh2/config; do
 
1433
            [[ -r $i ]] && config+=( "$i" )
1256
1434
        done
1257
1435
    fi
1258
1436
 
1259
1437
    # Known hosts files from configs
1260
 
    if [ ${#config[@]} -gt 0 ]; then
1261
 
        local OIFS=$IFS IFS=$'\n'
 
1438
    if [[ ${#config[@]} -gt 0 ]]; then
 
1439
        local OIFS=$IFS IFS=$'\n' j
1262
1440
        local -a tmpkh
1263
1441
        # expand paths (if present) to global and user known hosts files
1264
1442
        # TODO(?): try to make known hosts files with more than one consecutive
1265
1443
        #          spaces in their name work (watch out for ~ expansion
1266
1444
        #          breakage! Alioth#311595)
1267
1445
        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 ) )
 
1446
        IFS=$OIFS
1268
1447
        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" )
 
1448
            # First deal with quoted entries...
 
1449
            while [[ $i =~ ^([^\"]*)\"([^\"]*)\"(.*)$ ]]; do
 
1450
                i=${BASH_REMATCH[1]}${BASH_REMATCH[3]}
 
1451
                j=${BASH_REMATCH[2]}
 
1452
                __expand_tilde_by_ref j # Eval/expand possible `~' or `~user'
 
1453
                [[ -r $j ]] && kh+=( "$j" )
 
1454
            done
 
1455
            # ...and then the rest.
 
1456
            for j in $i; do
 
1457
                __expand_tilde_by_ref j # Eval/expand possible `~' or `~user'
 
1458
                [[ -r $j ]] && kh+=( "$j" )
 
1459
            done
1274
1460
        done
1275
 
        IFS=$OIFS
1276
1461
    fi
1277
1462
 
1278
 
    if [ -z "$configfile" ]; then
 
1463
    if [[ -z $configfile ]]; then
1279
1464
        # Global and user known_hosts files
1280
1465
        for i in /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2 \
1281
1466
            /etc/known_hosts /etc/known_hosts2 ~/.ssh/known_hosts \
1282
1467
            ~/.ssh/known_hosts2; do
1283
 
            [ -r $i ] && kh=( "${kh[@]}" $i )
 
1468
            [[ -r $i ]] && kh+=( "$i" )
1284
1469
        done
1285
1470
        for i in /etc/ssh2/knownhosts ~/.ssh2/hostkeys; do
1286
 
            [ -d $i ] && khd=( "${khd[@]}" $i/*pub )
 
1471
            [[ -d $i ]] && khd+=( "$i"/*pub )
1287
1472
        done
1288
1473
    fi
1289
1474
 
1301
1486
            # Digits followed by no dot or colon - search for digits followed
1302
1487
            # by a dot or a colon
1303
1488
            awkcur="^$awkcur.*[.:]"
1304
 
        elif [ -z "$awkcur" ]; then
 
1489
        elif [[ -z $awkcur ]]; then
1305
1490
            # A blank - search for a dot, a colon, or an alpha character
1306
1491
            awkcur="[a-z.:]"
1307
1492
        else
1308
1493
            awkcur="^$awkcur"
1309
1494
        fi
1310
1495
 
1311
 
        if [ ${#kh[@]} -gt 0 ]; then
 
1496
        if [[ ${#kh[@]} -gt 0 ]]; then
1312
1497
            # 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); \
 
1498
            COMPREPLY+=( $( awk 'BEGIN {FS=","}
 
1499
            /^\s*[^|\#]/ {
 
1500
            sub("^@[^ ]+ +", ""); \
 
1501
            sub(" .*$", ""); \
 
1502
            for (i=1; i<=NF; ++i) { \
1316
1503
            sub("^\\[", "", $i); sub("\\](:[0-9]+)?$", "", $i); \
1317
 
            if ($i ~ /'"$awkcur"'/) {print $i} \
 
1504
            if ($i !~ /[*?]/ && $i ~ /'"$awkcur"'/) {print $i} \
1318
1505
            }}' "${kh[@]}" 2>/dev/null ) )
1319
1506
        fi
1320
 
        if [ ${#khd[@]} -gt 0 ]; then
 
1507
        if [[ ${#khd[@]} -gt 0 ]]; then
1321
1508
            # Needs to look for files called
1322
1509
            # .../.ssh2/key_22_<hostname>.pub
1323
1510
            # dont fork any processes, because in a cluster environment,
1326
1513
                if [[ "$i" == *key_22_$curd*.pub && -r "$i" ]]; then
1327
1514
                    host=${i/#*key_22_/}
1328
1515
                    host=${host/%.pub/}
1329
 
                    COMPREPLY=( "${COMPREPLY[@]}" $host )
 
1516
                    COMPREPLY+=( $host )
1330
1517
                fi
1331
1518
            done
1332
1519
        fi
1340
1527
    # append any available aliases from config files
1341
1528
    if [[ ${#config[@]} -gt 0 && -n "$aliases" ]]; then
1342
1529
        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" \
 
1530
        COMPREPLY+=( $( compgen -P "$prefix$user" \
1344
1531
            -S "$suffix" -W "$hosts" -- "$cur" ) )
1345
1532
    fi
1346
1533
 
1347
 
    # Add hosts reported by avahi-browse, if desired and it's available.
1348
 
 
1349
1534
    # This feature is disabled because it does not scale to
1350
1535
    #  larger networks. See:
1351
1536
    # https://bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/510591
1352
1537
 
 
1538
    # Add hosts reported by avahi-browse, if desired and it's available.
1353
1539
    #if [[ ${COMP_KNOWN_HOSTS_WITH_AVAHI:-} ]] && \
1354
 
    #    type avahi-browse &>/dev/null; then
 
1540
        #type avahi-browse &>/dev/null; then
1355
1541
        # The original call to avahi-browse also had "-k", to avoid lookups
1356
1542
        # into avahi's services DB. We don't need the name of the service, and
1357
1543
        # if it contains ";", it may mistify the result. But on Gentoo (at
1358
1544
        # least), -k wasn't available (even if mentioned in the manpage) some
1359
1545
        # 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" ) )
 
1546
        #COMPREPLY+=( $( compgen -P "$prefix$user" -S "$suffix" -W \
 
1547
        #    "$( avahi-browse -cpr _workstation._tcp 2>/dev/null | \
 
1548
        #         awk -F';' '/^=/ { print $7 }' | sort -u )" -- "$cur" ) )
1364
1549
    #fi
1365
1550
 
 
1551
    # Add hosts reported by ruptime.
 
1552
    COMPREPLY+=( $( compgen -W \
 
1553
        "$( ruptime 2>/dev/null | awk '{ print $1 }' )" -- "$cur" ) )
 
1554
 
1366
1555
    # Add results of normal hostname completion, unless
1367
1556
    # `COMP_KNOWN_HOSTS_WITH_HOSTFILE' is set to an empty value.
1368
 
    if [ -n "${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1}" ]; then
1369
 
        COMPREPLY=( "${COMPREPLY[@]}"
 
1557
    if [[ -n ${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1} ]]; then
 
1558
        COMPREPLY+=(
1370
1559
            $( compgen -A hostname -P "$prefix$user" -S "$suffix" -- "$cur" ) )
1371
1560
    fi
1372
1561
 
1374
1563
 
1375
1564
    return 0
1376
1565
} # _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
 
1566
complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 \
 
1567
    fping fping6 telnet rsh rlogin ftp dig mtr ssh-installkeys showmount
1380
1568
 
1381
1569
# This meta-cd function observes the CDPATH variable, so that cd additionally
1382
1570
# completes on directories under those specified in CDPATH.
1383
1571
#
1384
1572
_cd()
1385
1573
{
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
 
1574
    local cur prev words cword
 
1575
    _init_completion || return
 
1576
 
 
1577
    local IFS=$'\n' i j k
 
1578
 
 
1579
    compopt -o filenames
1396
1580
 
1397
1581
    # Use standard dir completion if no CDPATH or parameter starts with /,
1398
1582
    # ./ or ../
1410
1594
        k="${#COMPREPLY[@]}"
1411
1595
        for j in $( compgen -d $i/$cur ); do
1412
1596
            if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
1413
 
                j="${j}/"
 
1597
                j+="/"
1414
1598
            fi
1415
1599
            COMPREPLY[k++]=${j#$i/}
1416
1600
        done
1451
1635
 
1452
1636
# A meta-command completion function for commands like sudo(8), which need to
1453
1637
# 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.
 
1638
# completion definition.
1456
1639
#
1457
1640
_command_offset()
1458
1641
{
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
1642
    # rewrite current completion context before invoking
1465
1643
    # actual command completion
1466
1644
 
1467
1645
    # find new first word position, then
1468
1646
    # 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
 
1647
    local word_offset=$1 i j
 
1648
    for (( i=0; i < $word_offset; i++ )); do
 
1649
        for (( j=0; j <= ${#COMP_LINE}; j++ )); do
 
1650
            [[ "$COMP_LINE" == "${COMP_WORDS[i]}"* ]] && break
 
1651
            COMP_LINE=${COMP_LINE:1}
 
1652
            ((COMP_POINT--))
 
1653
        done
 
1654
        COMP_LINE=${COMP_LINE#"${COMP_WORDS[i]}"}
 
1655
        ((COMP_POINT-=${#COMP_WORDS[i]}))
1475
1656
    done
1476
 
    COMP_LINE=${COMP_LINE:$char_offset}
1477
 
    COMP_POINT=$(( COMP_POINT - $char_offset ))
1478
1657
 
1479
1658
    # shift COMP_WORDS elements and adjust COMP_CWORD
1480
1659
    for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
1481
1660
        COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
1482
1661
    done
1483
1662
    for (( i; i <= COMP_CWORD; i++ )); do
1484
 
        unset COMP_WORDS[i];
 
1663
        unset COMP_WORDS[i]
1485
1664
    done
1486
 
    COMP_CWORD=$(( $COMP_CWORD - $word_offset ))
 
1665
    ((COMP_CWORD -= $word_offset))
1487
1666
 
1488
1667
    COMPREPLY=()
 
1668
    local cur
1489
1669
    _get_comp_words_by_ref cur
1490
1670
 
1491
1671
    if [[ $COMP_CWORD -eq 0 ]]; then
1492
 
        _compopt_o_filenames
1493
 
        COMPREPLY=( $( compgen -c -- "$cur" ) )
 
1672
        local IFS=$'\n'
 
1673
        compopt -o filenames
 
1674
        COMPREPLY=( $( compgen -d -c -- "$cur" ) )
1494
1675
    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
 
1676
        local cmd=${COMP_WORDS[0]} compcmd=${COMP_WORDS[0]}
 
1677
        local cspec=$( complete -p $cmd 2>/dev/null )
 
1678
 
 
1679
        # If we have no completion for $cmd yet, see if we have for basename
 
1680
        if [[ ! $cspec && $cmd == */* ]]; then
 
1681
            cspec=$( complete -p ${cmd##*/} 2>/dev/null )
 
1682
            [[ $cspec ]] && compcmd=${cmd##*/}
 
1683
        fi
 
1684
        # If still nothing, just load it for the basename
 
1685
        if [[ ! $cspec ]]; then
 
1686
            compcmd=${cmd##*/}
 
1687
            _completion_loader $compcmd
 
1688
            cspec=$( complete -p $compcmd 2>/dev/null )
 
1689
        fi
 
1690
 
 
1691
        if [[ -n $cspec ]]; then
 
1692
            if [[ ${cspec#* -F } != $cspec ]]; then
1499
1693
                # complete -F <function>
1500
1694
 
1501
1695
                # get function name
1502
 
                func=${cspec#*-F }
 
1696
                local func=${cspec#*-F }
1503
1697
                func=${func%% *}
1504
1698
 
1505
1699
                if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
1508
1702
                    $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
1509
1703
                fi
1510
1704
 
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
 
1705
                # restore initial compopts
 
1706
                local opt t
 
1707
                while true; do
 
1708
                    # FIXME: should we take "+o opt" into account?
 
1709
                    t=${cspec#*-o }
 
1710
                    if [[ $t == $cspec ]]; then
 
1711
                        break
1521
1712
                    fi
1522
 
                fi
1523
 
            elif [ -n "$cspec" ]; then
1524
 
                cspec=${cspec#complete};
1525
 
                cspec=${cspec%%${cmd##*/}};
1526
 
                COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
 
1713
                    opt=${t%% *}
 
1714
                    compopt -o $opt
 
1715
                    cspec=${t#$opt}
 
1716
                done
 
1717
            else
 
1718
                cspec=${cspec#complete}
 
1719
                cspec=${cspec%%$compcmd}
 
1720
                COMPREPLY=( $( eval compgen "$cspec" -- '$cur' ) )
1527
1721
            fi
1528
 
        elif [ ${#COMPREPLY[@]} -eq 0 ]; then
1529
 
            _filedir
 
1722
        elif [[ ${#COMPREPLY[@]} -eq 0 ]]; then
 
1723
            # XXX will probably never happen as long as completion loader loads
 
1724
            #     *something* for every command thrown at it ($cspec != empty)
 
1725
            _minimal
1530
1726
        fi
1531
1727
    fi
1532
1728
}
1537
1733
{
1538
1734
    local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
1539
1735
    local root_command=$1
1540
 
    _command $1 $2 $3
 
1736
    _command
1541
1737
}
1542
 
complete -F _root_command fakeroot gksu gksudo kdesudo really sudo
 
1738
complete -F _root_command fakeroot gksu gksudo kdesudo really
1543
1739
 
1544
1740
# Return true if the completion should be treated as running as root
1545
1741
_complete_as_root()
1549
1745
 
1550
1746
_longopt()
1551
1747
{
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]*)
 
1748
    local cur prev words cword split
 
1749
    _init_completion -s || return
 
1750
 
 
1751
    case "${prev,,}" in
 
1752
        --help|--usage|--version)
 
1753
            return 0
 
1754
            ;;
 
1755
        --*dir*)
1559
1756
            _filedir -d
1560
1757
            return 0
1561
1758
            ;;
1562
 
        --*[Ff][Ii][Ll][Ee]*|--*[Pp][Aa][Tt][Hh]*)
 
1759
        --*file*|--*path*)
1563
1760
            _filedir
1564
1761
            return 0
1565
1762
            ;;
 
1763
        --+([-a-z0-9_]))
 
1764
            local argtype=$( $1 --help 2>&1 | sed -ne \
 
1765
                "s|.*$prev\[\{0,1\}=[<[]\{0,1\}\([-A-Za-z0-9_]\{1,\}\).*|\1|p" )
 
1766
            case ${argtype,,} in
 
1767
                *dir*)
 
1768
                    _filedir -d
 
1769
                    return 0
 
1770
                    ;;
 
1771
                *file*|*path*)
 
1772
                    _filedir
 
1773
                    return 0
 
1774
                    ;;
 
1775
            esac
 
1776
            ;;
1566
1777
    esac
1567
1778
 
1568
1779
    $split && return 0
1569
1780
 
1570
1781
    if [[ "$cur" == -* ]]; then
1571
1782
        COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | \
1572
 
            sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}\).*/\1/p' | sort -u )" \
 
1783
            sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}=\{0,1\}\).*/\1/p' | sort -u )" \
1573
1784
            -- "$cur" ) )
 
1785
        [[ $COMPREPLY == *= ]] && compopt -o nospace
1574
1786
    elif [[ "$1" == @(mk|rm)dir ]]; then
1575
1787
        _filedir -d
1576
1788
    else
1578
1790
    fi
1579
1791
}
1580
1792
# 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 \
 
1793
complete -F _longopt a2ps awk base64 bash bc bison cat colordiff cp csplit \
 
1794
    cut date df diff dir du enscript env expand fmt fold gperf \
1583
1795
    grep grub head indent irb ld ldd less ln ls m4 md5sum mkdir mkfifo mknod \
1584
1796
    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
 
1797
    sed seq sha{,1,224,256,384,512}sum shar sort split strip sum tac tail tee \
 
1798
    texindex touch tr uname unexpand uniq units vdir wc wget who
1590
1799
 
 
1800
declare -A _xspecs
1591
1801
_filedir_xspec()
1592
1802
{
1593
 
    local IFS cur xspec
1594
 
 
1595
 
    IFS=$'\n'
1596
 
    COMPREPLY=()
1597
 
    _get_comp_words_by_ref cur
 
1803
    local cur prev words cword
 
1804
    _init_completion || return
1598
1805
 
1599
1806
    _expand || return 0
1600
1807
 
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
 
 
 
1808
    local IFS=$'\n' xspec=${_xspecs[${1##*/}]} tmp
1608
1809
    local -a toks
1609
 
    local tmp
1610
1810
 
1611
 
    toks=( ${toks[@]-} $(
 
1811
    toks=( $(
1612
1812
        compgen -d -- "$(quote_readline "$cur")" | {
1613
1813
        while read -r tmp; do
1614
 
            # see long TODO comment in _filedir() --David
1615
1814
            printf '%s\n' $tmp
1616
1815
        done
1617
1816
        }
1618
1817
        ))
1619
1818
 
1620
1819
    # Munge xspec to contain uppercase version too
 
1820
    # http://thread.gmane.org/gmane.comp.shells.bash.bugs/15294/focus=15306
1621
1821
    eval xspec="${xspec}"
1622
1822
    local matchop=!
1623
1823
    if [[ $xspec == !* ]]; then
1624
1824
        xspec=${xspec#!}
1625
1825
        matchop=@
1626
1826
    fi
1627
 
    [[ ${BASH_VERSINFO[0]} -ge 4 ]] && \
1628
 
        xspec="$matchop($xspec|${xspec^^})" || \
1629
 
        xspec="$matchop($xspec|$(printf %s $xspec | tr '[:lower:]' '[:upper:]'))"
 
1827
    xspec="$matchop($xspec|${xspec^^})"
1630
1828
 
1631
 
    toks=( ${toks[@]-} $(
 
1829
    toks+=( $(
1632
1830
        eval compgen -f -X "!$xspec" -- "\$(quote_readline "\$cur")" | {
1633
1831
        while read -r tmp; do
1634
 
            [ -n $tmp ] && printf '%s\n' $tmp
 
1832
            [[ -n $tmp ]] && printf '%s\n' $tmp
1635
1833
        done
1636
1834
        }
1637
1835
        ))
1638
1836
 
1639
 
    [ ${#toks[@]} -ne 0 ] && _compopt_o_filenames
1640
 
    COMPREPLY=( "${toks[@]}" )
 
1837
    if [[ ${#toks[@]} -ne 0 ]]; then
 
1838
        compopt -o filenames
 
1839
        COMPREPLY=( "${toks[@]}" )
 
1840
    fi
1641
1841
}
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 )
 
1842
 
 
1843
_install_xspec()
 
1844
{
 
1845
    local xspec=$1 cmd
 
1846
    shift
 
1847
    for cmd in $@; do
 
1848
        _xspecs[$cmd]=$xspec
1653
1849
    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
 
1850
    complete -F _filedir_xspec $@
 
1851
}
 
1852
# bzcmp, bzdiff, bz*grep, bzless, bzmore intentionally not here, see Debian: #455510
 
1853
_install_xspec '!*.?(t)bz?(2)' bunzip2 bzcat pbunzip2 pbzcat lbunzip2 lbzcat
 
1854
_install_xspec '!*.@(zip|[ejsw]ar|exe|pk3|wsz|zargo|xpi|sxw|o[tx]t|od[fgpst]|epub|apk)' unzip zipinfo
 
1855
_install_xspec '*.Z' compress znew
 
1856
# zcmp, zdiff, z*grep, zless, zmore intentionally not here, see Debian: #455510
 
1857
_install_xspec '!*.@(Z|[gGd]z|t[ag]z)' gunzip zcat unpigz
 
1858
_install_xspec '!*.Z' uncompress
 
1859
# lzcmp, lzdiff intentionally not here, see Debian: #455510
 
1860
_install_xspec '!*.@(tlz|lzma)' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma
 
1861
_install_xspec '!*.@(?(t)xz|tlz|lzma)' unxz xzcat
 
1862
_install_xspec '!*.lrz' lrunzip
 
1863
_install_xspec '!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx)' ee
 
1864
_install_xspec '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|svg)' qiv
 
1865
_install_xspec '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|?(e)ps)' xv
 
1866
_install_xspec '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview
 
1867
_install_xspec '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi kdvi
 
1868
_install_xspec '!*.dvi' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx
 
1869
_install_xspec '!*.[pf]df' acroread gpdf xpdf
 
1870
_install_xspec '!*.@(?(e)ps|pdf)' kpdf
 
1871
_install_xspec '!*.@(okular|@(?(e|x)ps|?(E|X)PS|[pf]df|[PF]DF|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)?(.?(gz|GZ|bz2|BZ2)))' okular
 
1872
_install_xspec '!*.pdf' epdfview
 
1873
_install_xspec '!*.@(?(e)ps|pdf)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr
 
1874
_install_xspec '!*.texi*' makeinfo texi2html
 
1875
_install_xspec '!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi
 
1876
_install_xspec '!*.mp3' mpg123 mpg321 madplay
 
1877
_install_xspec '!*@(.@(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[agmvx]|OG[AGMVX]|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
 
1878
_install_xspec '!*@(.@(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[agmvx]|OG[AGMVX]|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
 
1879
_install_xspec '!*.@(avi|asf|wmv)' aviplay
 
1880
_install_xspec '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay
 
1881
_install_xspec '!*.@(mpg|mpeg|avi|mov|qt)' xanim
 
1882
_install_xspec '!*.@(og[ag]|m3u|flac|spx)' ogg123
 
1883
_install_xspec '!*.@(mp3|og[ag]|pls|m3u)' gqmpeg freeamp
 
1884
_install_xspec '!*.fig' xfig
 
1885
_install_xspec '!*.@(mid?(i)|cmf)' playmidi
 
1886
_install_xspec '!*.@(mid?(i)|rmi|rcp|[gr]36|g18|mod|xm|it|x3m|s[3t]m|kar)' timidity
 
1887
_install_xspec '!*.@(669|abc|am[fs]|d[bs]m|dmf|far|it|mdl|m[eo]d|mid?(i)|mt[2m]|okta|p[st]m|s[3t]m|ult|umx|wav|xm)' modplugplay modplug123
 
1888
_install_xspec '*.@(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
 
1889
_install_xspec '!*.@(zip|z|gz|tgz)' bzme
 
1890
# konqueror not here on purpose, it's more than a web/html browser
 
1891
_install_xspec '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx opera galeon dillo elinks amaya firefox mozilla-firefox iceweasel google-chrome chromium-browser epiphany
 
1892
_install_xspec '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|?(f)odt|ott|odm)' oowriter
 
1893
_install_xspec '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|?(f)odp|otp)' ooimpress
 
1894
_install_xspec '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|?(f)ods|ots)' oocalc
 
1895
_install_xspec '!*.@(sxd|std|sda|sdd|?(f)odg|otg)' oodraw
 
1896
_install_xspec '!*.@(sxm|smf|mml|odf)' oomath
 
1897
_install_xspec '!*.odb' oobase
 
1898
_install_xspec '!*.[rs]pm' rpm2cpio
 
1899
_install_xspec '!*.aux' bibtex
 
1900
_install_xspec '!*.po' poedit gtranslator kbabel lokalize
 
1901
_install_xspec '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp
 
1902
_install_xspec '!*.[Hh][Rr][Bb]' hbrun
 
1903
_install_xspec '!*.ly' lilypond ly2dvi
 
1904
_install_xspec '!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))' cdiff
 
1905
_install_xspec '!@(*.@(ks|jks|jceks|p12|pfx|bks|ubr|gkr|cer|crt|cert|p7b|pkipath|pem|p10|csr|crl)|cacerts)' portecle
 
1906
_install_xspec '!*.@(mp[234c]|og[ag]|@(fl|a)ac|m4[abp]|spx|tta|w?(a)v|wma|aif?(f)|asf|ape)' kid3 kid3-qt
 
1907
unset -f _install_xspec
 
1908
 
 
1909
# Minimal completion to use as fallback in _completion_loader.
 
1910
_minimal()
 
1911
{
 
1912
    local cur prev words cword split
 
1913
    _init_completion -s || return
 
1914
    $split && return
 
1915
    _filedir
 
1916
}
 
1917
# Complete the empty string to allow completion of '>', '>>', and '<'
 
1918
# http://lists.gnu.org/archive/html/bug-bash/2012-01/msg00045.html
 
1919
complete -F _minimal ''
 
1920
 
 
1921
 
 
1922
# set up dynamic completion loading
 
1923
_completion_loader()
 
1924
{
 
1925
    local compdir=./completions
 
1926
    [[ $BASH_SOURCE == */* ]] && compdir="${BASH_SOURCE%/*}/completions"
 
1927
 
 
1928
    # Try basename.
 
1929
    . "$compdir/${1##*/}" &>/dev/null && return 124
 
1930
 
 
1931
    # Need to define *something*, otherwise there will be no completion at all.
 
1932
    complete -F _minimal "$1" && return 124
 
1933
} &&
 
1934
complete -D -F _completion_loader
 
1935
 
 
1936
# Function for loading and calling functions from dynamically loaded
 
1937
# completion files that may not have been sourced yet.
 
1938
# @param $1 completion file to load function from in case it is missing
 
1939
# @param $2... function and its arguments
 
1940
_xfunc()
 
1941
{
 
1942
    set -- "$@"
 
1943
    local srcfile=$1
 
1944
    shift
 
1945
    declare -F $1 &>/dev/null || {
 
1946
        local compdir=./completions
 
1947
        [[ $BASH_SOURCE == */* ]] && compdir="${BASH_SOURCE%/*}/completions"
 
1948
        . "$compdir/$srcfile"
 
1949
    }
 
1950
    "$@"
 
1951
}
 
1952
 
 
1953
# source compat completion directory definitions
1666
1954
if [[ -d $BASH_COMPLETION_COMPAT_DIR && -r $BASH_COMPLETION_COMPAT_DIR && \
1667
1955
    -x $BASH_COMPLETION_COMPAT_DIR ]]; then
1668
1956
    for i in $(LC_ALL=C command ls "$BASH_COMPLETION_COMPAT_DIR"); do
1669
1957
        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
 
1958
        [[ ${i##*/} != @($_backup_glob|Makefile*|$_blacklist_glob) \
 
1959
            && -f $i && -r $i ]] && . "$i"
 
1960
    done
 
1961
fi
 
1962
unset i _blacklist_glob
1684
1963
 
1685
1964
# source user completion file
1686
 
[[ $BASH_COMPLETION != ~/.bash_completion && -r ~/.bash_completion ]] \
 
1965
[[ ${BASH_SOURCE[0]} != ~/.bash_completion && -r ~/.bash_completion ]] \
1687
1966
    && . ~/.bash_completion
1688
1967
unset -f have
1689
 
unset UNAME USERLAND have
 
1968
unset have
1690
1969
 
1691
1970
set $BASH_COMPLETION_ORIGINAL_V_VALUE
1692
1971
unset BASH_COMPLETION_ORIGINAL_V_VALUE
1693
1972
 
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
1973
# ex: ts=4 sw=4 et filetype=sh