1 | #!/usr/bin/env bash
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 | function _suman_completer {
|
95 |
|
96 |
|
97 |
|
98 | local cmd_shortopts="-a -b -d -f -h -p -r -s -t -v -w"
|
99 | local cmd_longopts="--all --allow-reuse-image --append-match-all --append-match-any --append-match-none --babel-register --bail --cfg --cnvt --completion --concurrency --config --convert --coverage --create --cwd-is-root --cwd-is-tfd --daemon --dest --diagnostics --errors-only --fast --ff --fforce --force --force-cwd-root --force-cwd-to-be-project-root --force-cwd-to-test-file-dir --fst --full-stack-traces --groups --help --home --ignore-break --ignore-uncaught-exceptions --ignore-unhandled-rejections --inherit-stdio --init --install-globals --interactive --iue --iur --match-all --match-any --match-none --max-depth --no-allow-reuse-image --no-babel-register --no-color --no-colors --no-coverage-report --no-report --no-run --no-runner-lock --no-stream-to-console --no-stream-to-file --no-tables --no-transpile --no-use-babel-register --no-use-container --nt --pipe --postinstall --processes --procs --rand --random --recursive --remove-babel --repair --reporter-paths --reporters --rm-babel --rnr --runner --runner-lock --safe --server --shd --silent --sort-by-millis --src --stdout-silent --suman-helpers-dir --tail --touch --transpile --uninstall --uninstall-babel --use-babel --use-babel-register --use-container --use-istanbul --use-server --use-tap --use-tap-output --verbosity --version --vn --watch"
|
100 | local cmd_optargs="--append-match-all=arrayOfString --append-match-any=arrayOfString --append-match-none=arrayOfString --cfg=string --concurrency=integer --config=string --create=arrayOfString --dest=string --match-all=arrayOfString --match-any=arrayOfString --match-none=arrayOfString --max-depth=integer --processes=integer --procs=integer --reporter-paths=arrayOfString --reporters=arrayOfString --shd=string --src=string --suman-helpers-dir=string --verbosity=integer -v=integer"
|
101 |
|
102 |
|
103 |
|
104 |
|
105 | declare -a argv
|
106 |
|
107 |
|
108 |
|
109 |
|
110 | function trace {
|
111 | [[ -n "$_suman_log" ]] && echo "$*" >&2
|
112 | }
|
113 |
|
114 | function _dashdash_complete {
|
115 | local idx context
|
116 | idx=$1
|
117 | context=$2
|
118 |
|
119 | local shortopts longopts optargs subcmds allsubcmds argtypes
|
120 | shortopts="$(eval "echo \${cmd${context}_shortopts}")"
|
121 | longopts="$(eval "echo \${cmd${context}_longopts}")"
|
122 | optargs="$(eval "echo \${cmd${context}_optargs}")"
|
123 | subcmds="$(eval "echo \${cmd${context}_subcmds}")"
|
124 | allsubcmds="$(eval "echo \${cmd${context}_allsubcmds}")"
|
125 | IFS=', ' read -r -a argtypes <<< "$(eval "echo \${cmd${context}_argtypes}")"
|
126 |
|
127 | trace ""
|
128 | trace "_dashdash_complete(idx=$idx, context=$context)"
|
129 | trace " shortopts: $shortopts"
|
130 | trace " longopts: $longopts"
|
131 | trace " optargs: $optargs"
|
132 | trace " subcmds: $subcmds"
|
133 | trace " allsubcmds: $allsubcmds"
|
134 |
|
135 |
|
136 |
|
137 | local state=
|
138 | local nargs=0
|
139 | local i=$idx
|
140 | local argtype
|
141 | local optname
|
142 | local prefix
|
143 | local word
|
144 | local dashdashseen=
|
145 | while [[ $i -lt $len && $i -le $COMP_CWORD ]]; do
|
146 | argtype=
|
147 | optname=
|
148 | prefix=
|
149 | word=
|
150 |
|
151 | arg=${argv[$i]}
|
152 | trace " consider argv[$i]: '$arg'"
|
153 |
|
154 | if [[ "$arg" == "--" && $i -lt $COMP_CWORD ]]; then
|
155 | trace " dashdash seen"
|
156 | dashdashseen=yes
|
157 | state=arg
|
158 | word=$arg
|
159 | elif [[ -z "$dashdashseen" && "${arg:0:2}" == "--" ]]; then
|
160 | arg=${arg:2}
|
161 | if [[ "$arg" == *"="* ]]; then
|
162 | optname=${arg%%=*}
|
163 | val=${arg##*=}
|
164 | trace " long opt: optname='$optname' val='$val'"
|
165 | state=arg
|
166 | argtype=$(echo "$optargs" | awk -F "-$optname=" '{print $2}' | cut -d' ' -f1)
|
167 | word=$val
|
168 | prefix="--$optname="
|
169 | else
|
170 | optname=$arg
|
171 | val=
|
172 | trace " long opt: optname='$optname'"
|
173 | state=longopt
|
174 | word=--$optname
|
175 |
|
176 | if [[ "$optargs" == *"-$optname="* && $i -lt $COMP_CWORD ]]; then
|
177 | i=$(( $i + 1 ))
|
178 | state=arg
|
179 | argtype=$(echo "$optargs" | awk -F "-$optname=" '{print $2}' | cut -d' ' -f1)
|
180 | word=${argv[$i]}
|
181 | trace " takes arg (consume argv[$i], word='$word')"
|
182 | fi
|
183 | fi
|
184 | elif [[ -z "$dashdashseen" && "${arg:0:1}" == "-" ]]; then
|
185 | trace " short opt group"
|
186 | state=shortopt
|
187 | word=$arg
|
188 |
|
189 | local j=1
|
190 | while [[ $j -lt ${#arg} ]]; do
|
191 | optname=${arg:$j:1}
|
192 | trace " consider index $j: optname '$optname'"
|
193 |
|
194 | if [[ "$optargs" == *"-$optname="* ]]; then
|
195 | argtype=$(echo "$optargs" | awk -F "-$optname=" '{print $2}' | cut -d' ' -f1)
|
196 | if [[ $(( $j + 1 )) -lt ${#arg} ]]; then
|
197 | state=arg
|
198 | word=${arg:$(( $j + 1 ))}
|
199 | trace " takes arg (rest of this arg, word='$word', argtype='$argtype')"
|
200 | elif [[ $i -lt $COMP_CWORD ]]; then
|
201 | state=arg
|
202 | i=$(( $i + 1 ))
|
203 | word=${argv[$i]}
|
204 | trace " takes arg (word='$word', argtype='$argtype')"
|
205 | fi
|
206 | break
|
207 | fi
|
208 |
|
209 | j=$(( $j + 1 ))
|
210 | done
|
211 | elif [[ $i -lt $COMP_CWORD && -n "$arg" ]] && $(echo "$allsubcmds" | grep -w "$arg" >/dev/null); then
|
212 | trace " complete subcmd: recurse _dashdash_complete"
|
213 | _dashdash_complete $(( $i + 1 )) "${context}__${arg/-/_}"
|
214 | return
|
215 | else
|
216 | trace " not an opt or a complete subcmd"
|
217 | state=arg
|
218 | word=$arg
|
219 | nargs=$(( $nargs + 1 ))
|
220 | if [[ ${#argtypes[@]} -gt 0 ]]; then
|
221 | argtype="${argtypes[$(( $nargs - 1 ))]}"
|
222 | if [[ -z "$argtype" ]]; then
|
223 |
|
224 |
|
225 | argtype="${argtypes[@]: -1:1}"
|
226 | fi
|
227 | fi
|
228 | fi
|
229 |
|
230 | trace " state=$state prefix='$prefix' word='$word'"
|
231 | i=$(( $i + 1 ))
|
232 | done
|
233 |
|
234 | trace " parsed: state=$state optname='$optname' argtype='$argtype' prefix='$prefix' word='$word' dashdashseen=$dashdashseen"
|
235 | local compgen_opts=
|
236 | if [[ -n "$prefix" ]]; then
|
237 | compgen_opts="$compgen_opts -P $prefix"
|
238 | fi
|
239 |
|
240 | case $state in
|
241 | shortopt)
|
242 | compgen $compgen_opts -W "$shortopts $longopts" -- "$word"
|
243 | ;;
|
244 | longopt)
|
245 | compgen $compgen_opts -W "$longopts" -- "$word"
|
246 | ;;
|
247 | arg)
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 | if [[ "${word:0:1}" == '$' ]]; then
|
260 |
|
261 |
|
262 |
|
263 |
|
264 | trace " completing envvars"
|
265 | compgen $compgen_opts -P '$' -A export -- "${word:1}"
|
266 | elif [[ -z "$argtype" ]]; then
|
267 |
|
268 |
|
269 |
|
270 | if [[ -n "$dashdashseen" ]]; then
|
271 | trace " completing subcmds, if any (no argtype, dashdash seen)"
|
272 | compgen $compgen_opts -W "$subcmds" -- "$word"
|
273 | elif [[ -z "$word" ]]; then
|
274 | trace " completing subcmds, if any (no argtype, empty word)"
|
275 | compgen $compgen_opts -W "$subcmds" -- "$word"
|
276 | else
|
277 | trace " completing opts & subcmds (no argtype)"
|
278 | compgen $compgen_opts -W "$shortopts $longopts $subcmds" -- "$word"
|
279 | fi
|
280 | elif [[ $argtype == "none" ]]; then
|
281 |
|
282 |
|
283 | trace " completing 'none' (hack to imply no completions)"
|
284 | echo "##-no-completion- -results-##"
|
285 | elif [[ $argtype == "file" ]]; then
|
286 |
|
287 |
|
288 | trace " completing 'file' (let 'complete -o default' handle it)"
|
289 | echo ""
|
290 | elif ! type complete_$argtype 2>/dev/null >/dev/null; then
|
291 | trace " completing '$argtype' (fallback to default b/c complete_$argtype is unknown)"
|
292 | echo ""
|
293 | else
|
294 | trace " completing custom '$argtype'"
|
295 | completions=$(complete_$argtype "$word")
|
296 | if [[ -z "$completions" ]]; then
|
297 | trace " no custom '$argtype' completions"
|
298 |
|
299 |
|
300 | echo "##-no-completion- -results-##"
|
301 | else
|
302 | echo $completions
|
303 | fi
|
304 | fi
|
305 | ;;
|
306 | *)
|
307 | trace " unknown state: $state"
|
308 | ;;
|
309 | esac
|
310 | }
|
311 |
|
312 |
|
313 | trace ""
|
314 | trace "-- $(date)"
|
315 |
|
316 |
|
317 |
|
318 | trace "COMP_CWORD: '$COMP_CWORD'"
|
319 | trace "COMP_LINE: '$COMP_LINE'"
|
320 | trace "COMP_POINT: $COMP_POINT"
|
321 |
|
322 |
|
323 |
|
324 |
|
325 | if [[ $COMP_CWORD -lt 0 ]]; then
|
326 | trace "abort on negative COMP_CWORD"
|
327 | exit 1;
|
328 | fi
|
329 |
|
330 |
|
331 |
|
332 | shift
|
333 | i=0
|
334 | len=$#
|
335 | while [[ $# -gt 0 ]]; do
|
336 | argv[$i]=$1
|
337 | shift;
|
338 | i=$(( $i + 1 ))
|
339 | done
|
340 | trace "argv: '${argv[@]}'"
|
341 | trace "argv[COMP_CWORD-1]: '${argv[$(( $COMP_CWORD - 1 ))]}'"
|
342 | trace "argv[COMP_CWORD]: '${argv[$COMP_CWORD]}'"
|
343 | trace "argv len: '$len'"
|
344 |
|
345 | _dashdash_complete 1 ""
|
346 | }
|
347 |
|
348 |
|
349 |
|
350 |
|
351 |
|
352 |
|
353 | if type complete &>/dev/null; then
|
354 | function _suman_completion {
|
355 | local _log_file=/dev/null
|
356 | [[ -z "$_suman_log" ]] || _log_file="$_suman_log"
|
357 | COMPREPLY=($(COMP_CWORD="$COMP_CWORD" \
|
358 | COMP_LINE="$COMP_LINE" \
|
359 | COMP_POINT="$COMP_POINT" \
|
360 | _suman_completer -- "${COMP_WORDS[@]}" \
|
361 | 2>$_log_file)) || return $?
|
362 | }
|
363 | complete -o default -F _suman_completion suman
|
364 | elif type compdef &>/dev/null; then
|
365 | function _suman_completion {
|
366 | local _log_file=/dev/null
|
367 | [[ -z "$_suman_log" ]] || _log_file="$_suman_log"
|
368 | compadd -- $(COMP_CWORD=$((CURRENT-1)) \
|
369 | COMP_LINE=$BUFFER \
|
370 | COMP_POINT=0 \
|
371 | _suman_completer -- "${words[@]}" \
|
372 | 2>$_log_file)
|
373 | }
|
374 | compdef _suman_completion suman
|
375 | elif type compctl &>/dev/null; then
|
376 | function _suman_completion {
|
377 | local cword line point words si
|
378 | read -Ac words
|
379 | read -cn cword
|
380 | let cword-=1
|
381 | read -l line
|
382 | read -ln point
|
383 | local _log_file=/dev/null
|
384 | [[ -z "$_suman_log" ]] || _log_file="$_suman_log"
|
385 | reply=($(COMP_CWORD="$cword" \
|
386 | COMP_LINE="$line" \
|
387 | COMP_POINT="$point" \
|
388 | _suman_completer -- "${words[@]}" \
|
389 | 2>$_log_file)) || return $?
|
390 | }
|
391 | compctl -K _suman_completion suman
|
392 | fi
|
393 |
|