PageRenderTime 57ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/node_modules/dashdash/etc/dashdash.bash_completion.in

https://gitlab.com/Erdrix/archiveServices
Autoconf | 366 lines | 210 code | 35 blank | 121 comment | 35 complexity | 91f61ecc39a1959d7ce792f46b62a199 MD5 | raw file
  1. #!/bin/bash
  2. #
  3. # Bash completion generated for '{{name}}' at {{date}}.
  4. #
  5. # The original template lives here:
  6. # https://github.com/trentm/node-dashdash/blob/master/etc/dashdash.bash_completion.in
  7. #
  8. #
  9. # Copyright 2016 Trent Mick
  10. # Copyright 2016 Joyent, Inc.
  11. #
  12. #
  13. # A generic Bash completion driver script.
  14. #
  15. # This is meant to provide a re-usable chunk of Bash to use for
  16. # "etc/bash_completion.d/" files for individual tools. Only the "Configuration"
  17. # section with tool-specific info need differ. Features:
  18. #
  19. # - support for short and long opts
  20. # - support for knowing which options take arguments
  21. # - support for subcommands (e.g. 'git log <TAB>' to show just options for the
  22. # log subcommand)
  23. # - does the right thing with "--" to stop options
  24. # - custom optarg and arg types for custom completions
  25. # - (TODO) support for shells other than Bash (tcsh, zsh, fish?, etc.)
  26. #
  27. #
  28. # Examples/design:
  29. #
  30. # 1. Bash "default" completion. By default Bash's 'complete -o default' is
  31. # enabled. That means when there are no completions (e.g. if no opts match
  32. # the current word), then you'll get Bash's default completion. Most notably
  33. # that means you get filename completion. E.g.:
  34. # $ tool ./<TAB>
  35. # $ tool READ<TAB>
  36. #
  37. # 2. all opts and subcmds:
  38. # $ tool <TAB>
  39. # $ tool -v <TAB> # assuming '-v' doesn't take an arg
  40. # $ tool -<TAB> # matching opts
  41. # $ git lo<TAB> # matching subcmds
  42. #
  43. # Long opt completions are given *without* the '=', i.e. we prefer space
  44. # separated because that's easier for good completions.
  45. #
  46. # 3. long opt arg with '='
  47. # $ tool --file=<TAB>
  48. # $ tool --file=./d<TAB>
  49. # We maintain the "--file=" prefix. Limitation: With the attached prefix
  50. # the 'complete -o filenames' doesn't know to do dirname '/' suffixing. Meh.
  51. #
  52. # 4. envvars:
  53. # $ tool $<TAB>
  54. # $ tool $P<TAB>
  55. # Limitation: Currently only getting exported vars, so we miss "PS1" and
  56. # others.
  57. #
  58. # 5. Defer to other completion in a subshell:
  59. # $ tool --file $(cat ./<TAB>
  60. # We get this from 'complete -o default ...'.
  61. #
  62. # 6. Custom completion types from a provided bash function.
  63. # $ tool --profile <TAB> # complete available "profiles"
  64. #
  65. #
  66. # Dev Notes:
  67. # - compgen notes, from http://unix.stackexchange.com/questions/151118/understand-compgen-builtin-command
  68. # - https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html
  69. #
  70. # Debugging this completion:
  71. # 1. Uncomment the "_{{name}}_log_file=..." line.
  72. # 2. 'tail -f /var/tmp/dashdash-completion.log' in one terminal.
  73. # 3. Re-source this bash completion file.
  74. #_{{name}}_log=/var/tmp/dashdash-completion.log
  75. function _{{name}}_completer {
  76. # ---- cmd definition
  77. {{spec}}
  78. # ---- locals
  79. declare -a argv
  80. # ---- support functions
  81. function trace {
  82. [[ -n "$_{{name}}_log" ]] && echo "$*" >&2
  83. }
  84. function _dashdash_complete {
  85. local idx context
  86. idx=$1
  87. context=$2
  88. local shortopts="$(eval "echo \${cmd${context}_shortopts}")"
  89. local longopts="$(eval "echo \${cmd${context}_longopts}")"
  90. local optargs="$(eval "echo \${cmd${context}_optargs}")"
  91. local subcmds="$(eval "echo \${cmd${context}_subcmds}")"
  92. local allsubcmds="$(eval "echo \${cmd${context}_allsubcmds}")"
  93. trace ""
  94. trace "_dashdash_complete(idx=$idx, context=$context)"
  95. trace " shortopts: $shortopts"
  96. trace " longopts: $longopts"
  97. trace " optargs: $optargs"
  98. trace " subcmds: $subcmds"
  99. trace " allsubcmds: $allsubcmds"
  100. # Get 'state' of option parsing at this COMP_POINT.
  101. # Copying "dashdash.js#parse()" behaviour here.
  102. local state=
  103. local nargs=0
  104. local i=$idx
  105. local argtype
  106. local optname
  107. local prefix
  108. local word
  109. local dashdashseen=
  110. while [[ $i -lt $len && $i -le $COMP_CWORD ]]; do
  111. argtype=
  112. optname=
  113. prefix=
  114. word=
  115. arg=${argv[$i]}
  116. trace " consider argv[$i]: '$arg'"
  117. if [[ "$arg" == "--" && $i -lt $COMP_CWORD ]]; then
  118. trace " dashdash seen"
  119. dashdashseen=yes
  120. state=arg
  121. word=$arg
  122. elif [[ -z "$dashdashseen" && "${arg:0:2}" == "--" ]]; then
  123. arg=${arg:2}
  124. if [[ "$arg" == *"="* ]]; then
  125. optname=${arg%%=*}
  126. val=${arg##*=}
  127. trace " long opt: optname='$optname' val='$val'"
  128. state=arg
  129. argtype=$(echo "$optargs" | awk -F "-$optname=" '{print $2}' | cut -d' ' -f1)
  130. word=$val
  131. prefix="--$optname="
  132. else
  133. optname=$arg
  134. val=
  135. trace " long opt: optname='$optname'"
  136. state=longopt
  137. word=--$optname
  138. if [[ "$optargs" == *"-$optname="* && $i -lt $COMP_CWORD ]]; then
  139. i=$(( $i + 1 ))
  140. state=arg
  141. argtype=$(echo "$optargs" | awk -F "-$optname=" '{print $2}' | cut -d' ' -f1)
  142. word=${argv[$i]}
  143. trace " takes arg (consume argv[$i], word='$word')"
  144. fi
  145. fi
  146. elif [[ -z "$dashdashseen" && "${arg:0:1}" == "-" ]]; then
  147. trace " short opt group"
  148. state=shortopt
  149. word=$arg
  150. local j=1
  151. while [[ $j -lt ${#arg} ]]; do
  152. optname=${arg:$j:1}
  153. trace " consider index $j: optname '$optname'"
  154. if [[ "$optargs" == *"-$optname="* ]]; then
  155. argtype=$(echo "$optargs" | awk -F "-$optname=" '{print $2}' | cut -d' ' -f1)
  156. if [[ $(( $j + 1 )) -lt ${#arg} ]]; then
  157. state=arg
  158. word=${arg:$(( $j + 1 ))}
  159. trace " takes arg (rest of this arg, word='$word', argtype='$argtype')"
  160. elif [[ $i -lt $COMP_CWORD ]]; then
  161. state=arg
  162. i=$(( $i + 1 ))
  163. word=${argv[$i]}
  164. trace " takes arg (word='$word', argtype='$argtype')"
  165. fi
  166. break
  167. fi
  168. j=$(( $j + 1 ))
  169. done
  170. elif [[ $i -lt $COMP_CWORD && -n "$arg" ]] && $(echo "$allsubcmds" | grep -w "$arg" >/dev/null); then
  171. trace " complete subcmd: recurse _dashdash_complete"
  172. _dashdash_complete $(( $i + 1 )) "${context}__${arg/-/_}"
  173. return
  174. else
  175. trace " not an opt or a complete subcmd"
  176. state=arg
  177. word=$arg
  178. nargs=$(( $nargs + 1 ))
  179. fi
  180. trace " state=$state prefix='$prefix' word='$word'"
  181. i=$(( $i + 1 ))
  182. done
  183. trace " parsed: state=$state optname='$optname' argtype='$argtype' prefix='$prefix' word='$word' dashdashseen=$dashdashseen"
  184. local compgen_opts=
  185. if [[ -n "$prefix" ]]; then
  186. compgen_opts="$compgen_opts -P $prefix"
  187. fi
  188. case $state in
  189. shortopt)
  190. compgen $compgen_opts -W "$shortopts $longopts" -- "$word"
  191. ;;
  192. longopt)
  193. compgen $compgen_opts -W "$longopts" -- "$word"
  194. ;;
  195. arg)
  196. # If we don't know what completion to do, then emit nothing. We
  197. # expect that we are running with:
  198. # complete -o default ...
  199. # where "default" means: "Use Readline's default completion if
  200. # the compspec generates no matches." This gives us the good filename
  201. # completion, completion in subshells/backticks.
  202. #
  203. # We cannot support an argtype="directory" because
  204. # compgen -S '/' -A directory -- "$word"
  205. # doesn't give a satisfying result. It doesn't stop at the trailing '/'
  206. # so you cannot descend into dirs.
  207. if [[ "${word:0:1}" == '$' ]]; then
  208. # By default, Bash will complete '$<TAB>' to all envvars. Apparently
  209. # 'complete -o default' does *not* give us that. The following
  210. # gets *close* to the same completions: '-A export' misses envvars
  211. # like "PS1".
  212. trace " completing envvars"
  213. compgen $compgen_opts -P '$' -A export -- "${word:1}"
  214. elif [[ -z "$argtype" ]]; then
  215. if [[ -z "$dashdashseen" ]]; then
  216. trace " completing opts & subcmds (no argtype)"
  217. compgen $compgen_opts -W "$shortopts $longopts $subcmds" -- "$word"
  218. else
  219. trace " completing subcmds (no argtype, dashdash seen)"
  220. compgen $compgen_opts -W "$subcmds" -- "$word"
  221. fi
  222. elif [[ $argtype == "none" ]]; then
  223. # We want *no* completions, i.e. some way to get the active
  224. # 'complete -o default' to not do filename completion. Using
  225. # a single-space at least works in Bash on Mac OSX 10.11.
  226. trace " completing 'none' (hack to attempt to get no completions)"
  227. echo " "
  228. elif [[ $argtype == "file" ]]; then
  229. # 'complete -o default' gives the best filename completion, at least
  230. # on Mac.
  231. trace " completing 'file' (let 'complete -o default' handle it)"
  232. echo ""
  233. elif ! type complete_$argtype 2>/dev/null >/dev/null; then
  234. trace " completing '$argtype' (fallback to default b/c complete_$argtype is unknown)"
  235. echo ""
  236. else
  237. trace " completing custom '$argtype'"
  238. potentials=$(complete_$argtype "$word")
  239. compgen $compgen_opts -W "$potentials" -- "$word"
  240. fi
  241. ;;
  242. *)
  243. trace " unknown state: $state"
  244. ;;
  245. esac
  246. }
  247. trace ""
  248. trace "-- $(date)"
  249. #trace "\$IFS: '$IFS'"
  250. #trace "\$@: '$@'"
  251. #trace "COMP_WORDBREAKS: '$COMP_WORDBREAKS'"
  252. trace "COMP_CWORD: '$COMP_CWORD'"
  253. trace "COMP_LINE: '$COMP_LINE'"
  254. trace "COMP_POINT: $COMP_POINT"
  255. # Guard against negative COMP_CWORD. This is a Bash bug at least on
  256. # Mac 10.10.4's bash. See
  257. # <https://lists.gnu.org/archive/html/bug-bash/2009-07/msg00125.html>.
  258. if [[ $COMP_CWORD -lt 0 ]]; then
  259. trace "abort on negative COMP_CWORD"
  260. exit 1;
  261. fi
  262. # I don't know how to do array manip on argv vars,
  263. # so copy over to argv array to work on them.
  264. shift # the leading '--'
  265. i=0
  266. len=$#
  267. while [[ $# -gt 0 ]]; do
  268. argv[$i]=$1
  269. shift;
  270. i=$(( $i + 1 ))
  271. done
  272. trace "argv: '${argv[@]}'"
  273. trace "argv[COMP_CWORD-1]: '${argv[$(( $COMP_CWORD - 1 ))]}'"
  274. trace "argv[COMP_CWORD]: '${argv[$COMP_CWORD]}'"
  275. trace "argv len: '$len'"
  276. _dashdash_complete 1 ""
  277. }
  278. # ---- mainline
  279. # Note: This if-block to help work with 'compdef' and 'compctl' is
  280. # adapted from 'npm completion'.
  281. if type complete &>/dev/null; then
  282. function _{{name}}_completion {
  283. local _log_file=/dev/null
  284. [[ -z "$_{{name}}_log" ]] || _log_file="$_{{name}}_log"
  285. COMPREPLY=($(COMP_CWORD="$COMP_CWORD" \
  286. COMP_LINE="$COMP_LINE" \
  287. COMP_POINT="$COMP_POINT" \
  288. _{{name}}_completer -- "${COMP_WORDS[@]}" \
  289. 2>$_log_file)) || return $?
  290. }
  291. complete -o default -F _{{name}}_completion {{name}}
  292. elif type compdef &>/dev/null; then
  293. function _{{name}}_completion {
  294. local _log_file=/dev/null
  295. [[ -z "$_{{name}}_log" ]] || _log_file="$_{{name}}_log"
  296. compadd -- $(COMP_CWORD=$((CURRENT-1)) \
  297. COMP_LINE=$BUFFER \
  298. COMP_POINT=0 \
  299. _{{name}}_completer -- "${words[@]}" \
  300. 2>$_log_file)
  301. }
  302. compdef _{{name}}_completion {{name}}
  303. elif type compctl &>/dev/null; then
  304. function _{{name}}_completion {
  305. local cword line point words si
  306. read -Ac words
  307. read -cn cword
  308. let cword-=1
  309. read -l line
  310. read -ln point
  311. local _log_file=/dev/null
  312. [[ -z "$_{{name}}_log" ]] || _log_file="$_{{name}}_log"
  313. reply=($(COMP_CWORD="$cword" \
  314. COMP_LINE="$line" \
  315. COMP_POINT="$point" \
  316. _{{name}}_completer -- "${words[@]}" \
  317. 2>$_log_file)) || return $?
  318. }
  319. compctl -K _{{name}}_completion {{name}}
  320. fi
  321. ##
  322. ## This is a Bash completion file for the '{{name}}' command. You can install
  323. ## with either:
  324. ##
  325. ## cp FILE /usr/local/etc/bash_completion.d/{{name}}
  326. ##
  327. ## or:
  328. ##
  329. ## cp FILE > ~/.{{name}}.completion
  330. ## echo "source ~/.{{name}}.completion" >> ~/.bashrc
  331. ##