bash_completion 69 KB

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