Subversion Repositories configs

Rev

Details | Last modification | View Log | RSS feed

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