summaryrefslogtreecommitdiffstats
path: root/.local/share/bash/bash_completion
diff options
context:
space:
mode:
authorTyler Davis <tyler@gluecode.net>2024-01-10 12:13:23 -0800
committerTyler Davis <tyler@gluecode.net>2024-01-10 12:13:23 -0800
commit8c954408cf093378758d262c3088fc13a69f9639 (patch)
treed2fe4e65781224a679162ef2bc1610f1a5417245 /.local/share/bash/bash_completion
parent75415a836a83f6898515383107caa35b49cc48c4 (diff)
downloaddotfiles-8c954408cf093378758d262c3088fc13a69f9639.tar.gz
dotfiles-8c954408cf093378758d262c3088fc13a69f9639.zip
bin: add bash3 completion
Diffstat (limited to '.local/share/bash/bash_completion')
-rw-r--r--.local/share/bash/bash_completion1690
1 files changed, 1690 insertions, 0 deletions
diff --git a/.local/share/bash/bash_completion b/.local/share/bash/bash_completion
new file mode 100644
index 0000000..39ca929
--- /dev/null
+++ b/.local/share/bash/bash_completion
@@ -0,0 +1,1690 @@
+#
+# bash_completion - programmable completion functions for bash 3.2+
+#
+# Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
+# © 2009-2011, Bash Completion Maintainers
+# <bash-completion-devel@lists.alioth.debian.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The latest version of this software can be obtained here:
+#
+# http://bash-completion.alioth.debian.org/
+#
+# RELEASE: 1.3
+
+if [[ $- == *v* ]]; then
+ BASH_COMPLETION_ORIGINAL_V_VALUE="-v"
+else
+ BASH_COMPLETION_ORIGINAL_V_VALUE="+v"
+fi
+
+if [[ -n $BASH_COMPLETION_DEBUG ]]; then
+ set -v
+else
+ set +v
+fi
+
+# Alter the following to reflect the location of this file.
+#
+[ -n "$BASH_COMPLETION" ] || BASH_COMPLETION=$HOME/.local/share/bash/bash_completion
+[ -n "$BASH_COMPLETION_DIR" ] || BASH_COMPLETION_DIR=$HOME/.local/share/bash/bash_completion.d
+[ -n "$BASH_COMPLETION_COMPAT_DIR" ] || BASH_COMPLETION_COMPAT_DIR=$HOME/.local/share/bash/bash_completion.d
+readonly BASH_COMPLETION BASH_COMPLETION_DIR BASH_COMPLETION_COMPAT_DIR
+
+# Set a couple of useful vars
+#
+UNAME=$( uname -s )
+# strip OS type and version under Cygwin (e.g. CYGWIN_NT-5.1 => Cygwin)
+UNAME=${UNAME/CYGWIN_*/Cygwin}
+
+case ${UNAME} in
+ Linux|GNU|GNU/*) USERLAND=GNU ;;
+ *) USERLAND=${UNAME} ;;
+esac
+
+# Turn on extended globbing and programmable completion
+shopt -s extglob progcomp
+
+# A lot of the following one-liners were taken directly from the
+# completion examples provided with the bash 2.04 source distribution
+
+# Make directory commands see only directories
+complete -d pushd
+
+# The following section lists completions that are redefined later
+# Do NOT break these over multiple lines.
+#
+# START exclude -- do NOT remove this line
+# bzcmp, bzdiff, bz*grep, bzless, bzmore intentionally not here, see Debian: #455510
+complete -f -X '!*.?(t)bz?(2)' bunzip2 bzcat pbunzip2 pbzcat
+complete -f -X '!*.@(zip|[ejw]ar|exe|pk3|wsz|zargo|xpi|sxw|o[tx]t|od[fgpst]|epub|apk)' unzip zipinfo
+complete -f -X '*.Z' compress znew
+# zcmp, zdiff, z*grep, zless, zmore intentionally not here, see Debian: #455510
+complete -f -X '!*.@(Z|[gGd]z|t[ag]z)' gunzip zcat unpigz
+complete -f -X '!*.Z' uncompress
+# lzcmp, lzdiff intentionally not here, see Debian: #455510
+complete -f -X '!*.@(tlz|lzma)' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma
+complete -f -X '!*.@(?(t)xz|tlz|lzma)' unxz xzcat
+complete -f -X '!*.lrz' lrunzip
+complete -f -X '!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx)' ee
+complete -f -X '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm)' xv qiv
+complete -f -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview
+complete -f -X '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi kdvi
+complete -f -X '!*.dvi' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx
+complete -f -X '!*.[pf]df' acroread gpdf xpdf
+complete -f -X '!*.@(?(e)ps|pdf)' kpdf
+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
+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
+complete -f -X '!*.@(?(e)ps|pdf)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr
+complete -f -X '!*.texi*' makeinfo texi2html
+complete -f -X '!*.@(?(la)tex|texi|dtx|ins|ltx)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi
+complete -f -X '!*.mp3' mpg123 mpg321 madplay
+complete -f -X '!*@(.@(mp?(e)g|MP?(E)G|wma|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|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
+complete -f -X '!*@(.@(mp?(e)g|MP?(E)G|wma|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|wmv|mp[234]|MP[234]|m4[pv]|M4[PV]|mkv|MKV|og[gmv]|OG[GMV]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM|iso|ISO)|+([0-9]).@(vdr|VDR))?(.part)' kaffeine dragon
+complete -f -X '!*.@(avi|asf|wmv)' aviplay
+complete -f -X '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay
+complete -f -X '!*.@(mpg|mpeg|avi|mov|qt)' xanim
+complete -f -X '!*.@(ogg|m3u|flac|spx)' ogg123
+complete -f -X '!*.@(mp3|ogg|pls|m3u)' gqmpeg freeamp
+complete -f -X '!*.fig' xfig
+complete -f -X '!*.@(mid?(i)|cmf)' playmidi
+complete -f -X '!*.@(mid?(i)|rmi|rcp|[gr]36|g18|mod|xm|it|x3m|s[3t]m|kar)' timidity
+complete -f -X '!*.@(m[eo]d|s[3t]m|xm|it)' modplugplay modplug123
+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
+complete -f -X '!*.@([eE][xX][eE]?(.[sS][oO])|[cC][oO][mM]|[sS][cC][rR])' wine
+complete -f -X '!*.@(zip|z|gz|tgz)' bzme
+# konqueror not here on purpose, it's more than a web/html browser
+complete -f -X '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx opera galeon dillo elinks amaya firefox mozilla-firefox iceweasel google-chrome chromium-browser epiphany
+complete -f -X '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|odt|ott|odm)' oowriter
+complete -f -X '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|odp|otp)' ooimpress
+complete -f -X '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|ods|ots)' oocalc
+complete -f -X '!*.@(sxd|std|sda|sdd|odg|otg)' oodraw
+complete -f -X '!*.@(sxm|smf|mml|odf)' oomath
+complete -f -X '!*.odb' oobase
+complete -f -X '!*.[rs]pm' rpm2cpio
+complete -f -X '!*.aux' bibtex
+complete -f -X '!*.po' poedit gtranslator kbabel lokalize
+complete -f -X '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp
+complete -f -X '!*.[Hh][Rr][Bb]' hbrun
+complete -f -X '!*.ly' lilypond ly2dvi
+complete -f -X '!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))' cdiff
+complete -f -X '!*.lyx' lyx
+complete -f -X '!@(*.@(ks|jks|jceks|p12|pfx|bks|ubr|gkr|cer|crt|cert|p7b|pkipath|pem|p10|csr|crl)|cacerts)' portecle
+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
+# FINISH exclude -- do not remove this line
+
+# start of section containing compspecs that can be handled within bash
+
+# user commands see only users
+complete -u su write chfn groups slay w sux runuser
+
+# bg completes with stopped jobs
+complete -A stopped -P '"%' -S '"' bg
+
+# other job commands
+complete -j -P '"%' -S '"' fg jobs disown
+
+# readonly and unset complete with shell variables
+complete -v readonly unset
+
+# set completes with set options
+complete -A setopt set
+
+# shopt completes with shopt options
+complete -A shopt shopt
+
+# helptopics
+complete -A helptopic help
+
+# unalias completes with aliases
+complete -a unalias
+
+# bind completes with readline bindings (make this more intelligent)
+complete -A binding bind
+
+# type and which complete on commands
+complete -c command type which
+
+# builtin completes on builtins
+complete -b builtin
+
+# start of section containing completion functions called by other functions
+
+# This function checks whether we have a given program on the system.
+# No need for bulky functions in memory if we don't.
+#
+have()
+{
+ unset -v have
+ # Completions for system administrator commands are installed as well in
+ # case completion is attempted via `sudo command ...'.
+ PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 &>/dev/null &&
+ have="yes"
+}
+
+# This function checks whether a given readline variable
+# is `on'.
+#
+_rl_enabled()
+{
+ [[ "$( bind -v )" = *$1+([[:space:]])on* ]]
+}
+
+# This function shell-quotes the argument
+quote()
+{
+ echo \'${1//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
+}
+
+# @see _quote_readline_by_ref()
+quote_readline()
+{
+ local quoted
+ _quote_readline_by_ref "$1" ret
+ printf %s "$ret"
+} # quote_readline()
+
+
+# This function shell-dequotes the argument
+dequote()
+{
+ eval echo "$1" 2> /dev/null
+}
+
+
+# Assign variable one scope above the caller
+# Usage: local "$1" && _upvar $1 "value(s)"
+# Param: $1 Variable name to assign value to
+# Param: $* Value(s) to assign. If multiple values, an array is
+# assigned, otherwise a single value is assigned.
+# NOTE: For assigning multiple variables, use '_upvars'. Do NOT
+# use multiple '_upvar' calls, since one '_upvar' call might
+# reassign a variable to be used by another '_upvar' call.
+# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
+_upvar() {
+ if unset -v "$1"; then # Unset & validate varname
+ if (( $# == 2 )); then
+ eval $1=\"\$2\" # Return single value
+ else
+ eval $1=\(\"\${@:2}\"\) # Return array
+ fi
+ fi
+}
+
+
+# Assign variables one scope above the caller
+# Usage: local varname [varname ...] &&
+# _upvars [-v varname value] | [-aN varname [value ...]] ...
+# Available OPTIONS:
+# -aN Assign next N values to varname as array
+# -v Assign single value to varname
+# Return: 1 if error occurs
+# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
+_upvars() {
+ if ! (( $# )); then
+ echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
+ "value] | [-aN varname [value ...]] ..." 1>&2
+ return 2
+ fi
+ while (( $# )); do
+ case $1 in
+ -a*)
+ # Error checking
+ [[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1': missing"\
+ "number specifier" 1>&2; return 1; }
+ printf %d "${1#-a}" &> /dev/null || { echo "bash:"\
+ "${FUNCNAME[0]}: \`$1': invalid number specifier" 1>&2
+ return 1; }
+ # Assign array of -aN elements
+ [[ "$2" ]] && unset -v "$2" && eval $2=\(\"\${@:3:${1#-a}}\"\) &&
+ shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:"\
+ "\`$1${2+ }$2': missing argument(s)" 1>&2; return 1; }
+ ;;
+ -v)
+ # Assign single value
+ [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
+ shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\
+ "argument(s)" 1>&2; return 1; }
+ ;;
+ *)
+ echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2
+ return 1 ;;
+ esac
+ done
+}
+
+
+# Reassemble command line words, excluding specified characters from the
+# list of word completion separators (COMP_WORDBREAKS).
+# @param $1 chars Characters out of $COMP_WORDBREAKS which should
+# NOT be considered word breaks. This is useful for things like scp where
+# we want to return host:path and not only path, so we would pass the
+# colon (:) as $1 here.
+# @param $2 words Name of variable to return words to
+# @param $3 cword Name of variable to return cword to
+#
+__reassemble_comp_words_by_ref() {
+ local exclude i j ref
+ # Exclude word separator characters?
+ if [[ $1 ]]; then
+ # Yes, exclude word separator characters;
+ # Exclude only those characters, which were really included
+ exclude="${1//[^$COMP_WORDBREAKS]}"
+ fi
+
+ # Default to cword unchanged
+ eval $3=$COMP_CWORD
+ # Are characters excluded which were former included?
+ if [[ $exclude ]]; then
+ # Yes, list of word completion separators has shrunk;
+ # Re-assemble words to complete
+ for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
+ # Is current word not word 0 (the command itself) and is word not
+ # empty and is word made up of just word separator characters to be
+ # excluded?
+ while [[ $i -gt 0 && ${COMP_WORDS[$i]} &&
+ ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]}
+ ]]; do
+ [ $j -ge 2 ] && ((j--))
+ # Append word separator to current word
+ ref="$2[$j]"
+ eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+ # Indicate new cword
+ [ $i = $COMP_CWORD ] && eval $3=$j
+ # Indicate next word if available, else end *both* while and for loop
+ (( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
+ done
+ # Append word to current word
+ ref="$2[$j]"
+ eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+ # Indicate new cword
+ [[ $i == $COMP_CWORD ]] && eval $3=$j
+ done
+ else
+ # No, list of word completions separators hasn't changed;
+ eval $2=\( \"\${COMP_WORDS[@]}\" \)
+ fi
+} # __reassemble_comp_words_by_ref()
+
+
+# @param $1 exclude Characters out of $COMP_WORDBREAKS which should NOT be
+# considered word breaks. This is useful for things like scp where
+# we want to return host:path and not only path, so we would pass the
+# colon (:) as $1 in this case. Bash-3 doesn't do word splitting, so this
+# ensures we get the same word on both bash-3 and bash-4.
+# @param $2 words Name of variable to return words to
+# @param $3 cword Name of variable to return cword to
+# @param $4 cur Name of variable to return current word to complete to
+# @see ___get_cword_at_cursor_by_ref()
+__get_cword_at_cursor_by_ref() {
+ local cword words=()
+ __reassemble_comp_words_by_ref "$1" words cword
+
+ local i cur2
+ local cur="$COMP_LINE"
+ local index="$COMP_POINT"
+ for (( i = 0; i <= cword; ++i )); do
+ while [[
+ # Current word fits in $cur?
+ "${#cur}" -ge ${#words[i]} &&
+ # $cur doesn't match cword?
+ "${cur:0:${#words[i]}}" != "${words[i]}"
+ ]]; do
+ # Strip first character
+ cur="${cur:1}"
+ # Decrease cursor position
+ ((index--))
+ done
+
+ # Does found word matches cword?
+ if [[ "$i" -lt "$cword" ]]; then
+ # No, cword lies further;
+ local old_size="${#cur}"
+ cur="${cur#${words[i]}}"
+ local new_size="${#cur}"
+ index=$(( index - old_size + new_size ))
+ fi
+ done
+
+ if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
+ # We messed up. At least return the whole word so things keep working
+ cur2=${words[cword]}
+ else
+ cur2=${cur:0:$index}
+ fi
+
+ local "$2" "$3" "$4" &&
+ _upvars -a${#words[@]} $2 "${words[@]}" -v $3 "$cword" -v $4 "$cur2"
+}
+
+
+# Get the word to complete and optional previous words.
+# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
+# where the user is completing in the middle of a word.
+# (For example, if the line is "ls foobar",
+# and the cursor is here --------> ^
+# Also one is able to cross over possible wordbreak characters.
+# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
+# Available VARNAMES:
+# cur Return cur via $cur
+# prev Return prev via $prev
+# words Return words via $words
+# cword Return cword via $cword
+#
+# Available OPTIONS:
+# -n EXCLUDE Characters out of $COMP_WORDBREAKS which should NOT be
+# considered word breaks. This is useful for things like scp
+# where we want to return host:path and not only path, so we
+# would pass the colon (:) as -n option in this case. Bash-3
+# doesn't do word splitting, so this ensures we get the same
+# word on both bash-3 and bash-4.
+# -c VARNAME Return cur via $VARNAME
+# -p VARNAME Return prev via $VARNAME
+# -w VARNAME Return words via $VARNAME
+# -i VARNAME Return cword via $VARNAME
+#
+# Example usage:
+#
+# $ _get_comp_words_by_ref -n : cur prev
+#
+_get_comp_words_by_ref()
+{
+ local exclude flag i OPTIND=1
+ local cur cword words=()
+ local upargs=() upvars=() vcur vcword vprev vwords
+
+ while getopts "c:i:n:p:w:" flag "$@"; do
+ case $flag in
+ c) vcur=$OPTARG ;;
+ i) vcword=$OPTARG ;;
+ n) exclude=$OPTARG ;;
+ p) vprev=$OPTARG ;;
+ w) vwords=$OPTARG ;;
+ esac
+ done
+ while [[ $# -ge $OPTIND ]]; do
+ case ${!OPTIND} in
+ cur) vcur=cur ;;
+ prev) vprev=prev ;;
+ cword) vcword=cword ;;
+ words) vwords=words ;;
+ *) echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" \
+ 1>&2; return 1
+ esac
+ let "OPTIND += 1"
+ done
+
+ __get_cword_at_cursor_by_ref "$exclude" words cword cur
+
+ [[ $vcur ]] && { upvars+=("$vcur" ); upargs+=(-v $vcur "$cur" ); }
+ [[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
+ [[ $vprev ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev
+ "${words[cword - 1]}"); }
+ [[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
+ "${words[@]}"); }
+
+ (( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
+}
+
+
+# Get the word to complete.
+# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
+# where the user is completing in the middle of a word.
+# (For example, if the line is "ls foobar",
+# and the cursor is here --------> ^
+# @param $1 string Characters out of $COMP_WORDBREAKS which should NOT be
+# considered word breaks. This is useful for things like scp where
+# we want to return host:path and not only path, so we would pass the
+# colon (:) as $1 in this case. Bash-3 doesn't do word splitting, so this
+# ensures we get the same word on both bash-3 and bash-4.
+# @param $2 integer Index number of word to return, negatively offset to the
+# current word (default is 0, previous is 1), respecting the exclusions
+# given at $1. For example, `_get_cword "=:" 1' returns the word left of
+# the current word, respecting the exclusions "=:".
+# @deprecated Use `_get_comp_words_by_ref cur' instead
+# @see _get_comp_words_by_ref()
+_get_cword()
+{
+ local LC_CTYPE=C
+ local cword words
+ __reassemble_comp_words_by_ref "$1" words cword
+
+ # return previous word offset by $2
+ if [[ ${2//[^0-9]/} ]]; then
+ printf "%s" "${words[cword-$2]}"
+ elif [[ "${#words[cword]}" -eq 0 || "$COMP_POINT" == "${#COMP_LINE}" ]]; then
+ printf "%s" "${words[cword]}"
+ else
+ local i
+ local cur="$COMP_LINE"
+ local index="$COMP_POINT"
+ for (( i = 0; i <= cword; ++i )); do
+ while [[
+ # Current word fits in $cur?
+ "${#cur}" -ge ${#words[i]} &&
+ # $cur doesn't match cword?
+ "${cur:0:${#words[i]}}" != "${words[i]}"
+ ]]; do
+ # Strip first character
+ cur="${cur:1}"
+ # Decrease cursor position
+ ((index--))
+ done
+
+ # Does found word matches cword?
+ if [[ "$i" -lt "$cword" ]]; then
+ # No, cword lies further;
+ local old_size="${#cur}"
+ cur="${cur#${words[i]}}"
+ local new_size="${#cur}"
+ index=$(( index - old_size + new_size ))
+ fi
+ done
+
+ if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
+ # We messed up! At least return the whole word so things
+ # keep working
+ printf "%s" "${words[cword]}"
+ else
+ printf "%s" "${cur:0:$index}"
+ fi
+ fi
+} # _get_cword()
+
+
+# Get word previous to the current word.
+# This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4
+# will properly return the previous word with respect to any given exclusions to
+# COMP_WORDBREAKS.
+# @deprecated Use `_get_comp_words_by_ref cur prev' instead
+# @see _get_comp_words_by_ref()
+#
+_get_pword()
+{
+ if [ $COMP_CWORD -ge 1 ]; then
+ _get_cword "${@:-}" 1;
+ fi
+}
+
+
+# If the word-to-complete contains a colon (:), left-trim COMPREPLY items with
+# word-to-complete.
+# On bash-3, and bash-4 with a colon in COMP_WORDBREAKS, words containing
+# colons are always completed as entire words if the word to complete contains
+# a colon. This function fixes this, by removing the colon-containing-prefix
+# from COMPREPLY items.
+# The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in
+# your .bashrc:
+#
+# # Remove colon (:) from list of word completion separators
+# COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
+#
+# See also: Bash FAQ - E13) Why does filename completion misbehave if a colon
+# appears in the filename? - http://tiswww.case.edu/php/chet/bash/FAQ
+# @param $1 current word to complete (cur)
+# @modifies global array $COMPREPLY
+#
+__ltrim_colon_completions() {
+ # If word-to-complete contains a colon,
+ # and bash-version < 4,
+ # or bash-version >= 4 and COMP_WORDBREAKS contains a colon
+ if [[
+ "$1" == *:* && (
+ ${BASH_VERSINFO[0]} -lt 4 ||
+ (${BASH_VERSINFO[0]} -ge 4 && "$COMP_WORDBREAKS" == *:*)
+ )
+ ]]; then
+ # Remove colon-word prefix from COMPREPLY items
+ local colon_word=${1%${1##*:}}
+ local i=${#COMPREPLY[*]}
+ while [ $((--i)) -ge 0 ]; do
+ COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
+ done
+ fi
+} # __ltrim_colon_completions()
+
+
+# This function quotes the argument in a way so that readline dequoting
+# results in the original argument. This is necessary for at least
+# `compgen' which requires its arguments quoted/escaped:
+#
+# $ ls "a'b/"
+# c
+# $ compgen -f "a'b/" # Wrong, doesn't return output
+# $ compgen -f "a\'b/" # Good (bash-4)
+# a\'b/c
+# $ compgen -f "a\\\\\'b/" # Good (bash-3)
+# a\'b/c
+#
+# On bash-3, special characters need to be escaped extra. This is
+# unless the first character is a single quote ('). If the single
+# quote appears further down the string, bash default completion also
+# fails, e.g.:
+#
+# $ ls 'a&b/'
+# f
+# $ foo 'a&b/<TAB> # Becomes: foo 'a&b/f'
+# $ foo a'&b/<TAB> # Nothing happens
+#
+# See also:
+# - http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
+# - http://www.mail-archive.com/bash-completion-devel@lists.alioth.\
+# debian.org/msg01944.html
+# @param $1 Argument to quote
+# @param $2 Name of variable to return result to
+_quote_readline_by_ref()
+{
+ if [[ ${1:0:1} == "'" ]]; then
+ if [[ ${BASH_VERSINFO[0]} -ge 4 ]]; then
+ # Leave out first character
+ printf -v $2 %s "${1:1}"
+ else
+ # Quote word, leaving out first character
+ printf -v $2 %q "${1:1}"
+ # Double-quote word (bash-3)
+ printf -v $2 %q ${!2}
+ fi
+ elif [[ ${BASH_VERSINFO[0]} -le 3 && ${1:0:1} == '"' ]]; then
+ printf -v $2 %q "${1:1}"
+ else
+ printf -v $2 %q "$1"
+ fi
+
+ # If result becomes quoted like this: $'string', re-evaluate in order to
+ # drop the additional quoting. See also: http://www.mail-archive.com/
+ # bash-completion-devel@lists.alioth.debian.org/msg01942.html
+ [[ ${!2:0:1} == '$' ]] && eval $2=${!2}
+} # _quote_readline_by_ref()
+
+
+# This function turns on "-o filenames" behavior dynamically. It is present
+# for bash < 4 reasons. See http://bugs.debian.org/272660#64 for info about
+# the bash < 4 compgen hack.
+_compopt_o_filenames()
+{
+ # We test for compopt availability first because directly invoking it on
+ # bash < 4 at this point may cause terminal echo to be turned off for some
+ # reason, see https://bugzilla.redhat.com/653669 for more info.
+ type compopt &>/dev/null && compopt -o filenames 2>/dev/null || \
+ compgen -f /non-existing-dir/ >/dev/null
+}
+
+
+# This function performs file and directory completion. It's better than
+# simply using 'compgen -f', because it honours spaces in filenames.
+# @param $1 If `-d', complete only on directories. Otherwise filter/pick only
+# completions with `.$1' and the uppercase version of it as file
+# extension.
+#
+_filedir()
+{
+ local i IFS=$'\n' xspec
+
+ _tilde "$cur" || return 0
+
+ local -a toks
+ local quoted tmp
+
+ _quote_readline_by_ref "$cur" quoted
+ toks=( ${toks[@]-} $(
+ compgen -d -- "$cur" | {
+ while read -r tmp; do
+ # TODO: I have removed a "[ -n $tmp ] &&" before 'printf ..',
+ # and everything works again. If this bug suddenly
+ # appears again (i.e. "cd /b<TAB>" becomes "cd /"),
+ # remember to check for other similar conditionals (here
+ # and _filedir_xspec()). --David
+ printf '%s\n' $tmp
+ done
+ }
+ ))
+
+ if [[ "$1" != -d ]]; then
+ # Munge xspec to contain uppercase version too
+ [[ ${BASH_VERSINFO[0]} -ge 4 ]] && \
+ xspec=${1:+"!*.@($1|${1^^})"} || \
+ xspec=${1:+"!*.@($1|$(printf %s $1 | tr '[:lower:]' '[:upper:]'))"}
+ toks=( ${toks[@]-} $( compgen -f -X "$xspec" -- $quoted) )
+ fi
+ [ ${#toks[@]} -ne 0 ] && _compopt_o_filenames
+
+ COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" )
+} # _filedir()
+
+
+# This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it
+# easier to support both "--foo bar" and "--foo=bar" style completions.
+# Returns 0 if current option was split, 1 otherwise.
+#
+_split_longopt()
+{
+ if [[ "$cur" == --?*=* ]]; then
+ # Cut also backslash before '=' in case it ended up there
+ # for some reason.
+ prev="${cur%%?(\\)=*}"
+ cur="${cur#*=}"
+ return 0
+ fi
+
+ return 1
+}
+
+# This function tries to parse the help output of the given command.
+# @param $1 command
+# @param $2 command options (default: --help)
+#
+_parse_help() {
+ $1 ${2:---help} 2>&1 | sed -e '/^[[:space:]]*-/!d' -e 's|[,/]| |g' | \
+ awk '{ print $1; if ($2 ~ /^-/) { print $2 } }' | sed -e 's|[<=].*||'
+}
+
+# This function completes on signal names
+#
+_signals()
+{
+ local i
+
+ # standard signal completion is rather braindead, so we need
+ # to hack around to get what we want here, which is to
+ # complete on a dash, followed by the signal name minus
+ # the SIG prefix
+ COMPREPLY=( $( compgen -A signal SIG${cur#-} ))
+ for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
+ COMPREPLY[i]=-${COMPREPLY[i]#SIG}
+ done
+}
+
+# This function completes on known mac addresses
+#
+_mac_addresses()
+{
+ local re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}'
+ local PATH="$PATH:/sbin:/usr/sbin"
+
+ # Local interfaces (Linux only?)
+ COMPREPLY=( "${COMPREPLY[@]}" $( ifconfig -a 2>/dev/null | sed -ne \
+ "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" ) )
+
+ # ARP cache
+ COMPREPLY=( "${COMPREPLY[@]}" $( arp -an 2>/dev/null | sed -ne \
+ "s/.*[[:space:]]\($re\)[[:space:]].*/\1/p" -ne \
+ "s/.*[[:space:]]\($re\)[[:space:]]*$/\1/p" ) )
+
+ # /etc/ethers
+ COMPREPLY=( "${COMPREPLY[@]}" $( sed -ne \
+ "s/^[[:space:]]*\($re\)[[:space:]].*/\1/p" /etc/ethers 2>/dev/null ) )
+
+ COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+}
+
+# This function completes on configured network interfaces
+#
+_configured_interfaces()
+{
+ if [ -f /etc/debian_version ]; then
+ # Debian system
+ COMPREPLY=( $( compgen -W "$( sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p'\
+ /etc/network/interfaces )" -- "$cur" ) )
+ elif [ -f /etc/SuSE-release ]; then
+ # SuSE system
+ COMPREPLY=( $( compgen -W "$( printf '%s\n' \
+ /etc/sysconfig/network/ifcfg-* | \
+ sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
+ elif [ -f /etc/pld-release ]; then
+ # PLD Linux
+ COMPREPLY=( $( compgen -W "$( command ls -B \
+ /etc/sysconfig/interfaces | \
+ sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
+ else
+ # Assume Red Hat
+ COMPREPLY=( $( compgen -W "$( printf '%s\n' \
+ /etc/sysconfig/network-scripts/ifcfg-* | \
+ sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
+ fi
+}
+
+# This function completes on available kernels
+#
+_kernel_versions()
+{
+ COMPREPLY=( $( compgen -W '$( command ls /lib/modules )' -- "$cur" ) )
+}
+
+# This function completes on all available network interfaces
+# -a: restrict to active interfaces only
+# -w: restrict to wireless interfaces only
+#
+_available_interfaces()
+{
+ local cmd
+
+ if [ "${1:-}" = -w ]; then
+ cmd="iwconfig"
+ elif [ "${1:-}" = -a ]; then
+ cmd="ifconfig"
+ else
+ cmd="ifconfig -a"
+ fi
+
+ COMPREPLY=( $( eval PATH="$PATH:/sbin" $cmd 2>/dev/null | \
+ awk '/^[^ \t]/ { print $1 }' ) )
+ COMPREPLY=( $( compgen -W '${COMPREPLY[@]/%[[:punct:]]/}' -- "$cur" ) )
+}
+
+
+# Perform tilde (~) completion
+# @return True (0) if completion needs further processing,
+# False (> 0) if tilde is followed by a valid username, completions
+# are put in COMPREPLY and no further processing is necessary.
+_tilde() {
+ local result=0
+ # Does $1 start with tilde (~) and doesn't contain slash (/)?
+ if [[ ${1:0:1} == "~" && $1 == ${1//\/} ]]; then
+ _compopt_o_filenames
+ # Try generate username completions
+ COMPREPLY=( $( compgen -P '~' -u "${1#\~}" ) )
+ result=${#COMPREPLY[@]}
+ fi
+ return $result
+}
+
+
+# Expand variable starting with tilde (~)
+# We want to expand ~foo/... to /home/foo/... to avoid problems when
+# word-to-complete starting with a tilde is fed to commands and ending up
+# quoted instead of expanded.
+# Only the first portion of the variable from the tilde up to the first slash
+# (~../) is expanded. The remainder of the variable, containing for example
+# a dollar sign variable ($) or asterisk (*) is not expanded.
+# Example usage:
+#
+# $ v="~"; __expand_tilde_by_ref v; echo "$v"
+#
+# Example output:
+#
+# v output
+# -------- ----------------
+# ~ /home/user
+# ~foo/bar /home/foo/bar
+# ~foo/$HOME /home/foo/$HOME
+# ~foo/a b /home/foo/a b
+# ~foo/* /home/foo/*
+#
+# @param $1 Name of variable (not the value of the variable) to expand
+__expand_tilde_by_ref() {
+ # Does $1 start with tilde (~)?
+ if [ "${!1:0:1}" = "~" ]; then
+ # Does $1 contain slash (/)?
+ if [ "${!1}" != "${!1//\/}" ]; then
+ # Yes, $1 contains slash;
+ # 1: Remove * including and after first slash (/), i.e. "~a/b"
+ # becomes "~a". Double quotes allow eval.
+ # 2: Remove * before the first slash (/), i.e. "~a/b"
+ # becomes "b". Single quotes prevent eval.
+ # +-----1----+ +---2----+
+ eval $1="${!1/%\/*}"/'${!1#*/}'
+ else
+ # No, $1 doesn't contain slash
+ eval $1="${!1}"
+ fi
+ fi
+} # __expand_tilde_by_ref()
+
+
+# This function expands tildes in pathnames
+#
+_expand()
+{
+ # FIXME: Why was this here?
+ #[ "$cur" != "${cur%\\}" ] && cur="$cur\\"
+
+ # Expand ~username type directory specifications. We want to expand
+ # ~foo/... to /home/foo/... to avoid problems when $cur starting with
+ # a tilde is fed to commands and ending up quoted instead of expanded.
+
+ if [[ "$cur" == \~*/* ]]; then
+ eval cur=$cur
+ elif [[ "$cur" == \~* ]]; then
+ cur=${cur#\~}
+ COMPREPLY=( $( compgen -P '~' -u "$cur" ) )
+ [ ${#COMPREPLY[@]} -eq 1 ] && eval COMPREPLY[0]=${COMPREPLY[0]}
+ return ${#COMPREPLY[@]}
+ fi
+}
+
+# This function completes on process IDs.
+# AIX and Solaris ps prefers X/Open syntax.
+[[ $UNAME == SunOS || $UNAME == AIX ]] &&
+_pids()
+{
+ COMPREPLY=( $( compgen -W '$( command ps -efo pid | sed 1d )' -- "$cur" ))
+} ||
+_pids()
+{
+ COMPREPLY=( $( compgen -W '$( command ps axo pid= )' -- "$cur" ) )
+}
+
+# This function completes on process group IDs.
+# AIX and SunOS prefer X/Open, all else should be BSD.
+[[ $UNAME == SunOS || $UNAME == AIX ]] &&
+_pgids()
+{
+ COMPREPLY=( $( compgen -W '$( command ps -efo pgid | sed 1d )' -- "$cur" ))
+} ||
+_pgids()
+{
+ COMPREPLY=( $( compgen -W '$( command ps axo pgid= )' -- "$cur" ))
+}
+
+# This function completes on process names.
+# AIX and SunOS prefer X/Open, all else should be BSD.
+[[ $UNAME == SunOS || $UNAME == AIX ]] &&
+_pnames()
+{
+ COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps -efo comm | \
+ sed -e 1d -e "s:.*/::" -e "s/^-//" | sort -u )' -- "$cur" ) )
+} ||
+_pnames()
+{
+ # FIXME: completes "[kblockd/0]" to "0". Previously it was completed
+ # to "kblockd" which isn't correct either. "kblockd/0" would be
+ # arguably most correct, but killall from psmisc 22 treats arguments
+ # containing "/" specially unless -r is given so that wouldn't quite
+ # work either. Perhaps it'd be best to not complete these to anything
+ # for now.
+ # Not using "ps axo comm" because under some Linux kernels, it
+ # truncates command names (see e.g. http://bugs.debian.org/497540#19)
+ COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps axo command= | \
+ sed -e "s/ .*//" -e "s:.*/::" -e "s/:$//" -e "s/^[[(-]//" \
+ -e "s/[])]$//" | sort -u )' -- "$cur" ) )
+}
+
+# This function completes on user IDs
+#
+_uids()
+{
+ if type getent &>/dev/null; then
+ COMPREPLY=( $( compgen -W '$( getent passwd | cut -d: -f3 )' -- "$cur" ) )
+ elif type perl &>/dev/null; then
+ COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"' )' -- "$cur" ) )
+ else
+ # make do with /etc/passwd
+ COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/passwd )' -- "$cur" ) )
+ fi
+}
+
+# This function completes on group IDs
+#
+_gids()
+{
+ if type getent &>/dev/null; then
+ COMPREPLY=( $( compgen -W '$( getent group | cut -d: -f3 )' \
+ -- "$cur" ) )
+ elif type perl &>/dev/null; then
+ COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"' )' -- "$cur" ) )
+ else
+ # make do with /etc/group
+ COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/group )' -- "$cur" ) )
+ fi
+}
+
+# This function completes on services
+#
+_services()
+{
+ local sysvdir famdir
+ [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d || sysvdir=/etc/init.d
+ famdir=/etc/xinetd.d
+ COMPREPLY=( $( printf '%s\n' \
+ $sysvdir/!(*.rpm@(orig|new|save)|*~|functions) ) )
+
+ if [ -d $famdir ]; then
+ COMPREPLY=( "${COMPREPLY[@]}" $( printf '%s\n' \
+ $famdir/!(*.rpm@(orig|new|save)|*~) ) )
+ fi
+
+ COMPREPLY=( $( compgen -W '${COMPREPLY[@]#@($sysvdir|$famdir)/}' -- "$cur" ) )
+}
+
+# This function completes on modules
+#
+_modules()
+{
+ local modpath
+ modpath=/lib/modules/$1
+ COMPREPLY=( $( compgen -W "$( command ls -R $modpath | \
+ sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.gz\)\{0,1\}$/\1/p' )" -- "$cur" ) )
+}
+
+# This function completes on installed modules
+#
+_installed_modules()
+{
+ COMPREPLY=( $( compgen -W "$( PATH="$PATH:/sbin" lsmod | \
+ awk '{if (NR != 1) print $1}' )" -- "$1" ) )
+}
+
+# This function completes on user or user:group format; as for chown and cpio.
+#
+# The : must be added manually; it will only complete usernames initially.
+# The legacy user.group format is not supported.
+#
+# @param $1 If -u, only return users/groups the user has access to in
+# context of current completion.
+_usergroup()
+{
+ if [[ $cur = *\\\\* || $cur = *:*:* ]]; then
+ # Give up early on if something seems horribly wrong.
+ return
+ elif [[ $cur = *\\:* ]]; then
+ # Completing group after 'user\:gr<TAB>'.
+ # Reply with a list of groups prefixed with 'user:', readline will
+ # escape to the colon.
+ local prefix
+ prefix=${cur%%*([^:])}
+ prefix=${prefix//\\}
+ local mycur="${cur#*[:]}"
+ if [[ $1 == -u ]]; then
+ _allowed_groups "$mycur"
+ else
+ local IFS=$'\n'
+ COMPREPLY=( $( compgen -g -- "$mycur" ) )
+ fi
+ COMPREPLY=( $( compgen -P "$prefix" -W "${COMPREPLY[@]}" ) )
+ elif [[ $cur = *:* ]]; then
+ # Completing group after 'user:gr<TAB>'.
+ # Reply with a list of unprefixed groups since readline with split on :
+ # and only replace the 'gr' part
+ local mycur="${cur#*:}"
+ if [[ $1 == -u ]]; then
+ _allowed_groups "$mycur"
+ else
+ local IFS=$'\n'
+ COMPREPLY=( $( compgen -g -- "$mycur" ) )
+ fi
+ else
+ # Completing a partial 'usernam<TAB>'.
+ #
+ # Don't suffix with a : because readline will escape it and add a
+ # slash. It's better to complete into 'chown username ' than 'chown
+ # username\:'.
+ if [[ $1 == -u ]]; then
+ _allowed_users "$cur"
+ else
+ local IFS=$'\n'
+ COMPREPLY=( $( compgen -u -- "$cur" ) )
+ fi
+ fi
+}
+
+_allowed_users()
+{
+ if _complete_as_root; then
+ local IFS=$'\n'
+ COMPREPLY=( $( compgen -u -- "${1:-$cur}" ) )
+ else
+ local IFS=$'\n '
+ COMPREPLY=( $( compgen -W \
+ "$( id -un 2>/dev/null || whoami 2>/dev/null )" -- "${1:-$cur}" ) )
+ fi
+}
+
+_allowed_groups()
+{
+ if _complete_as_root; then
+ local IFS=$'\n'
+ COMPREPLY=( $( compgen -g -- "$1" ) )
+ else
+ local IFS=$'\n '
+ COMPREPLY=( $( compgen -W \
+ "$( id -Gn 2>/dev/null || groups 2>/dev/null )" -- "$1" ) )
+ fi
+}
+
+# This function completes on valid shells
+#
+_shells()
+{
+ COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W \
+ '$( command grep "^[[:space:]]*/" /etc/shells 2>/dev/null )' \
+ -- "$cur" ) )
+}
+
+# This function completes on valid filesystem types
+#
+_fstypes()
+{
+ local fss
+
+ if [ -e /proc/filesystems ] ; then
+ # Linux
+ fss="$( cut -d$'\t' -f2 /proc/filesystems )
+ $( awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null )"
+ else
+ # Generic
+ fss="$( awk '/^[ \t]*[^#]/ { print $3 }' /etc/fstab 2>/dev/null )
+ $( awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null )
+ $( awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null )
+ $( awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null )
+ $( [ -d /etc/fs ] && command ls /etc/fs )"
+ fi
+
+ [ -n "$fss" ] && \
+ COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$fss" -- "$cur" ) )
+}
+
+# Get real command.
+# - arg: $1 Command
+# - stdout: Filename of command in PATH with possible symbolic links resolved.
+# Empty string if command not found.
+# - return: True (0) if command found, False (> 0) if not.
+_realcommand()
+{
+ type -P "$1" > /dev/null && {
+ if type -p realpath > /dev/null; then
+ realpath "$(type -P "$1")"
+ elif type -p readlink > /dev/null; then
+ readlink "$(type -P "$1")"
+ else
+ type -P "$1"
+ fi
+ }
+}
+
+# This function returns the first arugment, excluding options
+# @param $1 chars Characters out of $COMP_WORDBREAKS which should
+# NOT be considered word breaks. See __reassemble_comp_words_by_ref.
+_get_first_arg()
+{
+ local i
+
+ arg=
+ for (( i=1; i < COMP_CWORD; i++ )); do
+ if [[ "${COMP_WORDS[i]}" != -* ]]; then
+ arg=${COMP_WORDS[i]}
+ break
+ fi
+ done
+}
+
+
+# This function counts the number of args, excluding options
+# @param $1 chars Characters out of $COMP_WORDBREAKS which should
+# NOT be considered word breaks. See __reassemble_comp_words_by_ref.
+_count_args()
+{
+ local i cword words
+ __reassemble_comp_words_by_ref "$1" words cword
+
+ args=1
+ for i in "${words[@]:1:cword-1}"; do
+ [[ "$i" != -* ]] && args=$(($args+1))
+ done
+}
+
+# This function completes on PCI IDs
+#
+_pci_ids()
+{
+ COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
+ "$( PATH="$PATH:/sbin" lspci -n | awk '{print $3}')" -- "$cur" ) )
+}
+
+# This function completes on USB IDs
+#
+_usb_ids()
+{
+ COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
+ "$( PATH="$PATH:/sbin" lsusb | awk '{print $6}' )" -- "$cur" ) )
+}
+
+# CD device names
+_cd_devices()
+{
+ COMPREPLY=( "${COMPREPLY[@]}"
+ $( compgen -f -d -X "!*/?([amrs])cd*" -- "${cur:-/dev/}" ) )
+}
+
+# DVD device names
+_dvd_devices()
+{
+ COMPREPLY=( "${COMPREPLY[@]}"
+ $( compgen -f -d -X "!*/?(r)dvd*" -- "${cur:-/dev/}" ) )
+}
+
+# start of section containing completion functions for external programs
+
+# a little help for FreeBSD ports users
+[ $UNAME = FreeBSD ] && complete -W 'index search fetch fetch-list extract \
+ patch configure build install reinstall deinstall clean clean-depends \
+ kernel buildworld' make
+
+# This function provides simple user@host completion
+#
+_user_at_host() {
+ local cur
+
+ COMPREPLY=()
+ _get_comp_words_by_ref -n : cur
+
+ if [[ $cur == *@* ]]; then
+ _known_hosts_real "$cur"
+ else
+ COMPREPLY=( $( compgen -u -- "$cur" ) )
+ fi
+
+ return 0
+}
+shopt -u hostcomplete && complete -F _user_at_host -o nospace talk ytalk finger
+
+# NOTE: Using this function as a helper function is deprecated. Use
+# `_known_hosts_real' instead.
+_known_hosts()
+{
+ local options
+ COMPREPLY=()
+
+ # NOTE: Using `_known_hosts' as a helper function and passing options
+ # to `_known_hosts' is deprecated: Use `_known_hosts_real' instead.
+ [[ "$1" == -a || "$2" == -a ]] && options=-a
+ [[ "$1" == -c || "$2" == -c ]] && options="$options -c"
+ _known_hosts_real $options "$(_get_cword :)"
+} # _known_hosts()
+
+# Helper function for completing _known_hosts.
+# This function performs host completion based on ssh's config and known_hosts
+# files, as well as hostnames reported by avahi-browse if
+# COMP_KNOWN_HOSTS_WITH_AVAHI is set to a non-empty value. Also hosts from
+# HOSTFILE (compgen -A hostname) are added, unless
+# COMP_KNOWN_HOSTS_WITH_HOSTFILE is set to an empty value.
+# Usage: _known_hosts_real [OPTIONS] CWORD
+# Options: -a Use aliases
+# -c Use `:' suffix
+# -F configfile Use `configfile' for configuration settings
+# -p PREFIX Use PREFIX
+# Return: Completions, starting with CWORD, are added to COMPREPLY[]
+_known_hosts_real()
+{
+ local configfile flag prefix
+ local cur curd awkcur user suffix aliases i host
+ local -a kh khd config
+
+ local OPTIND=1
+ while getopts "acF:p:" flag "$@"; do
+ case $flag in
+ a) aliases='yes' ;;
+ c) suffix=':' ;;
+ F) configfile=$OPTARG ;;
+ p) prefix=$OPTARG ;;
+ esac
+ done
+ [ $# -lt $OPTIND ] && echo "error: $FUNCNAME: missing mandatory argument CWORD"
+ cur=${!OPTIND}; let "OPTIND += 1"
+ [ $# -ge $OPTIND ] && echo "error: $FUNCNAME("$@"): unprocessed arguments:"\
+ $(while [ $# -ge $OPTIND ]; do printf '%s\n' ${!OPTIND}; shift; done)
+
+ [[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
+ kh=()
+
+ # ssh config files
+ if [ -n "$configfile" ]; then
+ [ -r "$configfile" ] &&
+ config=( "${config[@]}" "$configfile" )
+ else
+ for i in /etc/ssh/ssh_config "${HOME}/.ssh/config" \
+ "${HOME}/.ssh2/config"; do
+ [ -r $i ] && config=( "${config[@]}" "$i" )
+ done
+ fi
+
+ # Known hosts files from configs
+ if [ ${#config[@]} -gt 0 ]; then
+ local OIFS=$IFS IFS=$'\n'
+ local -a tmpkh
+ # expand paths (if present) to global and user known hosts files
+ # TODO(?): try to make known hosts files with more than one consecutive
+ # spaces in their name work (watch out for ~ expansion
+ # breakage! Alioth#311595)
+ 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 ) )
+ for i in "${tmpkh[@]}"; do
+ # Remove possible quotes
+ i=${i//\"}
+ # Eval/expand possible `~' or `~user'
+ __expand_tilde_by_ref i
+ [ -r "$i" ] && kh=( "${kh[@]}" "$i" )
+ done
+ IFS=$OIFS
+ fi
+
+ if [ -z "$configfile" ]; then
+ # Global and user known_hosts files
+ for i in /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2 \
+ /etc/known_hosts /etc/known_hosts2 ~/.ssh/known_hosts \
+ ~/.ssh/known_hosts2; do
+ [ -r $i ] && kh=( "${kh[@]}" $i )
+ done
+ for i in /etc/ssh2/knownhosts ~/.ssh2/hostkeys; do
+ [ -d $i ] && khd=( "${khd[@]}" $i/*pub )
+ done
+ fi
+
+ # If we have known_hosts files to use
+ if [[ ${#kh[@]} -gt 0 || ${#khd[@]} -gt 0 ]]; then
+ # Escape slashes and dots in paths for awk
+ awkcur=${cur//\//\\\/}
+ awkcur=${awkcur//\./\\\.}
+ curd=$awkcur
+
+ if [[ "$awkcur" == [0-9]*[.:]* ]]; then
+ # Digits followed by a dot or a colon - just search for that
+ awkcur="^$awkcur[.:]*"
+ elif [[ "$awkcur" == [0-9]* ]]; then
+ # Digits followed by no dot or colon - search for digits followed
+ # by a dot or a colon
+ awkcur="^$awkcur.*[.:]"
+ elif [ -z "$awkcur" ]; then
+ # A blank - search for a dot, a colon, or an alpha character
+ awkcur="[a-z.:]"
+ else
+ awkcur="^$awkcur"
+ fi
+
+ if [ ${#kh[@]} -gt 0 ]; then
+ # FS needs to look for a comma separated list
+ COMPREPLY=( "${COMPREPLY[@]}" $( awk 'BEGIN {FS=","}
+ /^\s*[^|\#]/ {for (i=1; i<=2; ++i) { \
+ sub(" .*$", "", $i); \
+ sub("^\\[", "", $i); sub("\\](:[0-9]+)?$", "", $i); \
+ if ($i ~ /'"$awkcur"'/) {print $i} \
+ }}' "${kh[@]}" 2>/dev/null ) )
+ fi
+ if [ ${#khd[@]} -gt 0 ]; then
+ # Needs to look for files called
+ # .../.ssh2/key_22_<hostname>.pub
+ # dont fork any processes, because in a cluster environment,
+ # there can be hundreds of hostkeys
+ for i in "${khd[@]}" ; do
+ if [[ "$i" == *key_22_$curd*.pub && -r "$i" ]]; then
+ host=${i/#*key_22_/}
+ host=${host/%.pub/}
+ COMPREPLY=( "${COMPREPLY[@]}" $host )
+ fi
+ done
+ fi
+
+ # apply suffix and prefix
+ for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
+ COMPREPLY[i]=$prefix$user${COMPREPLY[i]}$suffix
+ done
+ fi
+
+ # append any available aliases from config files
+ if [[ ${#config[@]} -gt 0 && -n "$aliases" ]]; then
+ local hosts=$( sed -ne 's/^[[:blank:]]*[Hh][Oo][Ss][Tt]\([Nn][Aa][Mm][Ee]\)\{0,1\}[[:blank:]]\{1,\}\([^#*?]*\)\(#.*\)\{0,1\}$/\2/p' "${config[@]}" )
+ COMPREPLY=( "${COMPREPLY[@]}" $( compgen -P "$prefix$user" \
+ -S "$suffix" -W "$hosts" -- "$cur" ) )
+ fi
+
+ # Add hosts reported by avahi-browse, if desired and it's available.
+ if [[ ${COMP_KNOWN_HOSTS_WITH_AVAHI:-} ]] && \
+ type avahi-browse &>/dev/null; then
+ # The original call to avahi-browse also had "-k", to avoid lookups
+ # into avahi's services DB. We don't need the name of the service, and
+ # if it contains ";", it may mistify the result. But on Gentoo (at
+ # least), -k wasn't available (even if mentioned in the manpage) some
+ # time ago, so...
+ COMPREPLY=( "${COMPREPLY[@]}" $( \
+ compgen -P "$prefix$user" -S "$suffix" -W \
+ "$( avahi-browse -cpr _workstation._tcp 2>/dev/null | \
+ awk -F';' '/^=/ { print $7 }' | sort -u )" -- "$cur" ) )
+ fi
+
+ # Add results of normal hostname completion, unless
+ # `COMP_KNOWN_HOSTS_WITH_HOSTFILE' is set to an empty value.
+ if [ -n "${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1}" ]; then
+ COMPREPLY=( "${COMPREPLY[@]}"
+ $( compgen -A hostname -P "$prefix$user" -S "$suffix" -- "$cur" ) )
+ fi
+
+ __ltrim_colon_completions "$prefix$user$cur"
+
+ return 0
+} # _known_hosts_real()
+complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 ping \
+ ping6 fping fping6 telnet host nslookup rsh rlogin ftp dig mtr \
+ ssh-installkeys showmount
+
+# This meta-cd function observes the CDPATH variable, so that cd additionally
+# completes on directories under those specified in CDPATH.
+#
+_cd()
+{
+ local cur IFS=$'\n' i j k
+ _get_comp_words_by_ref cur
+
+ # try to allow variable completion
+ if [[ "$cur" == ?(\\)\$* ]]; then
+ COMPREPLY=( $( compgen -v -P '$' -- "${cur#?(\\)$}" ) )
+ return 0
+ fi
+
+ _compopt_o_filenames
+
+ # Use standard dir completion if no CDPATH or parameter starts with /,
+ # ./ or ../
+ if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
+ _filedir -d
+ return 0
+ fi
+
+ local -r mark_dirs=$(_rl_enabled mark-directories && echo y)
+ local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y)
+
+ # we have a CDPATH, so loop on its contents
+ for i in ${CDPATH//:/$'\n'}; do
+ # create an array of matched subdirs
+ k="${#COMPREPLY[@]}"
+ for j in $( compgen -d $i/$cur ); do
+ if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
+ j="${j}/"
+ fi
+ COMPREPLY[k++]=${j#$i/}
+ done
+ done
+
+ _filedir -d
+
+ if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
+ i=${COMPREPLY[0]}
+ if [[ "$i" == "$cur" && $i != "*/" ]]; then
+ COMPREPLY[0]="${i}/"
+ fi
+ fi
+
+ return 0
+}
+if shopt -q cdable_vars; then
+ complete -v -F _cd -o nospace cd
+else
+ complete -F _cd -o nospace cd
+fi
+
+# a wrapper method for the next one, when the offset is unknown
+_command()
+{
+ local offset i
+
+ # find actual offset, as position of the first non-option
+ offset=1
+ for (( i=1; i <= COMP_CWORD; i++ )); do
+ if [[ "${COMP_WORDS[i]}" != -* ]]; then
+ offset=$i
+ break
+ fi
+ done
+ _command_offset $offset
+}
+
+# A meta-command completion function for commands like sudo(8), which need to
+# first complete on a command, then complete according to that command's own
+# completion definition - currently not quite foolproof (e.g. mount and umount
+# don't work properly), but still quite useful.
+#
+_command_offset()
+{
+ local cur func cline cspec noglob cmd i char_offset word_offset \
+ _COMMAND_FUNC _COMMAND_FUNC_ARGS
+
+ word_offset=$1
+
+ # rewrite current completion context before invoking
+ # actual command completion
+
+ # find new first word position, then
+ # rewrite COMP_LINE and adjust COMP_POINT
+ local first_word=${COMP_WORDS[$word_offset]}
+ for (( i=0; i <= ${#COMP_LINE}; i++ )); do
+ if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
+ char_offset=$i
+ break
+ fi
+ done
+ COMP_LINE=${COMP_LINE:$char_offset}
+ COMP_POINT=$(( COMP_POINT - $char_offset ))
+
+ # shift COMP_WORDS elements and adjust COMP_CWORD
+ for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
+ COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
+ done
+ for (( i; i <= COMP_CWORD; i++ )); do
+ unset COMP_WORDS[i];
+ done
+ COMP_CWORD=$(( $COMP_CWORD - $word_offset ))
+
+ COMPREPLY=()
+ _get_comp_words_by_ref cur
+
+ if [[ $COMP_CWORD -eq 0 ]]; then
+ _compopt_o_filenames
+ COMPREPLY=( $( compgen -c -- "$cur" ) )
+ else
+ cmd=${COMP_WORDS[0]}
+ if complete -p ${cmd##*/} &>/dev/null; then
+ cspec=$( complete -p ${cmd##*/} )
+ if [ "${cspec#* -F }" != "$cspec" ]; then
+ # complete -F <function>
+
+ # get function name
+ func=${cspec#*-F }
+ func=${func%% *}
+
+ if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
+ $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
+ else
+ $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
+ fi
+
+ # remove any \: generated by a command that doesn't
+ # default to filenames or dirnames (e.g. sudo chown)
+ # FIXME: I'm pretty sure this does not work!
+ if [ "${cspec#*-o }" != "$cspec" ]; then
+ cspec=${cspec#*-o }
+ cspec=${cspec%% *}
+ if [[ "$cspec" != @(dir|file)names ]]; then
+ COMPREPLY=("${COMPREPLY[@]//\\\\:/:}")
+ else
+ _compopt_o_filenames
+ fi
+ fi
+ elif [ -n "$cspec" ]; then
+ cspec=${cspec#complete};
+ cspec=${cspec%%${cmd##*/}};
+ COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
+ fi
+ elif [ ${#COMPREPLY[@]} -eq 0 ]; then
+ _filedir
+ fi
+ fi
+}
+complete -F _command aoss command do else eval exec ltrace nice nohup padsp \
+ then time tsocks vsound xargs
+
+_root_command()
+{
+ local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
+ local root_command=$1
+ _command $1 $2 $3
+}
+complete -F _root_command fakeroot gksu gksudo kdesudo really sudo
+
+# Return true if the completion should be treated as running as root
+_complete_as_root()
+{
+ [[ $EUID -eq 0 || ${root_command:-} ]]
+}
+
+_longopt()
+{
+ local cur prev split=false
+ _get_comp_words_by_ref -n = cur prev
+
+ _split_longopt && split=true
+
+ case "$prev" in
+ --*[Dd][Ii][Rr]*)
+ _filedir -d
+ return 0
+ ;;
+ --*[Ff][Ii][Ll][Ee]*|--*[Pp][Aa][Tt][Hh]*)
+ _filedir
+ return 0
+ ;;
+ esac
+
+ $split && return 0
+
+ if [[ "$cur" == -* ]]; then
+ COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | \
+ sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}\).*/\1/p' | sort -u )" \
+ -- "$cur" ) )
+ elif [[ "$1" == @(mk|rm)dir ]]; then
+ _filedir -d
+ else
+ _filedir
+ fi
+}
+# makeinfo and texi2dvi are defined elsewhere.
+for i in a2ps awk bash bc bison cat colordiff cp csplit \
+ curl cut date df diff dir du enscript env expand fmt fold gperf gprof \
+ grep grub head indent irb ld ldd less ln ls m4 md5sum mkdir mkfifo mknod \
+ mv netstat nl nm objcopy objdump od paste patch pr ptx readelf rm rmdir \
+ sed seq sha{,1,224,256,384,512}sum shar sort split strip tac tail tee \
+ texindex touch tr uname unexpand uniq units vdir wc wget who; do
+ have $i && complete -F _longopt -o default $i
+done
+unset i
+
+_filedir_xspec()
+{
+ local IFS cur xspec
+
+ IFS=$'\n'
+ COMPREPLY=()
+ _get_comp_words_by_ref cur
+
+ _expand || return 0
+
+ # get first exclusion compspec that matches this command
+ xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \$0; exit }" \
+ "$BASH_COMPLETION" )
+ # prune to leave nothing but the -X spec
+ xspec=${xspec#*-X }
+ xspec=${xspec%% *}
+
+ local -a toks
+ local tmp
+
+ toks=( ${toks[@]-} $(
+ compgen -d -- "$(quote_readline "$cur")" | {
+ while read -r tmp; do
+ # see long TODO comment in _filedir() --David
+ printf '%s\n' $tmp
+ done
+ }
+ ))
+
+ # Munge xspec to contain uppercase version too
+ eval xspec="${xspec}"
+ local matchop=!
+ if [[ $xspec == !* ]]; then
+ xspec=${xspec#!}
+ matchop=@
+ fi
+ [[ ${BASH_VERSINFO[0]} -ge 4 ]] && \
+ xspec="$matchop($xspec|${xspec^^})" || \
+ xspec="$matchop($xspec|$(printf %s $xspec | tr '[:lower:]' '[:upper:]'))"
+
+ toks=( ${toks[@]-} $(
+ eval compgen -f -X "!$xspec" -- "\$(quote_readline "\$cur")" | {
+ while read -r tmp; do
+ [ -n $tmp ] && printf '%s\n' $tmp
+ done
+ }
+ ))
+
+ [ ${#toks[@]} -ne 0 ] && _compopt_o_filenames
+ COMPREPLY=( "${toks[@]}" )
+}
+list=( $( sed -ne '/^# START exclude/,/^# FINISH exclude/p' "$BASH_COMPLETION" | \
+ # read exclusion compspecs
+ (
+ while read line
+ do
+ # ignore compspecs that are commented out
+ if [ "${line#\#}" != "$line" ]; then continue; fi
+ line=${line%# START exclude*}
+ line=${line%# FINISH exclude*}
+ line=${line##*\'}
+ list=( "${list[@]}" $line )
+ done
+ printf '%s ' "${list[@]}"
+ )
+ ) )
+# remove previous compspecs
+if [ ${#list[@]} -gt 0 ]; then
+ eval complete -r ${list[@]}
+ # install new compspecs
+ eval complete -F _filedir_xspec "${list[@]}"
+fi
+unset list
+
+# source completion directory definitions
+if [[ -d $BASH_COMPLETION_COMPAT_DIR && -r $BASH_COMPLETION_COMPAT_DIR && \
+ -x $BASH_COMPLETION_COMPAT_DIR ]]; then
+ for i in $(LC_ALL=C command ls "$BASH_COMPLETION_COMPAT_DIR"); do
+ i=$BASH_COMPLETION_COMPAT_DIR/$i
+ [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)|Makefile*) \
+ && -f $i && -r $i ]] && . "$i"
+ done
+fi
+if [[ $BASH_COMPLETION_DIR != $BASH_COMPLETION_COMPAT_DIR && \
+ -d $BASH_COMPLETION_DIR && -r $BASH_COMPLETION_DIR && \
+ -x $BASH_COMPLETION_DIR ]]; then
+ for i in $(LC_ALL=C command ls "$BASH_COMPLETION_DIR"); do
+ i=$BASH_COMPLETION_DIR/$i
+ [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)|Makefile*) \
+ && -f $i && -r $i ]] && . "$i"
+ done
+fi
+unset i
+
+# source user completion file
+[[ $BASH_COMPLETION != ~/.bash_completion && -r ~/.bash_completion ]] \
+ && . ~/.bash_completion
+unset -f have
+unset UNAME USERLAND have
+
+set $BASH_COMPLETION_ORIGINAL_V_VALUE
+unset BASH_COMPLETION_ORIGINAL_V_VALUE
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 4
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# ex: ts=4 sw=4 et filetype=sh