PageRenderTime 61ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/bash_completion

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