1 |
|
2 | ## oils_failures_allowed: 9
|
3 | ## compare_shells: bash
|
4 |
|
5 | #### complete with no args and complete -p both print completion spec
|
6 |
|
7 | set -e
|
8 |
|
9 | complete
|
10 |
|
11 | complete -W 'foo bar' mycommand
|
12 |
|
13 | complete -p
|
14 |
|
15 | complete -F myfunc other
|
16 |
|
17 | complete
|
18 |
|
19 | ## STDOUT:
|
20 | complete -W 'foo bar' mycommand
|
21 | complete -W 'foo bar' mycommand
|
22 | complete -F myfunc other
|
23 | ## END
|
24 |
|
25 | #### complete -F f is usage error
|
26 |
|
27 | #complete -F f cmd
|
28 |
|
29 | # Alias for complete -p
|
30 | complete > /dev/null # ignore OSH output for now
|
31 | echo status=$?
|
32 |
|
33 | # But this is an error
|
34 | complete -F f
|
35 | echo status=$?
|
36 |
|
37 | ## STDOUT:
|
38 | status=0
|
39 | status=2
|
40 | ## END
|
41 |
|
42 | #### complete with nonexistent function
|
43 | complete -F invalidZZ -D
|
44 | echo status=$?
|
45 | ## stdout: status=2
|
46 | ## BUG bash stdout: status=0
|
47 |
|
48 | #### complete with no action
|
49 | complete foo
|
50 | echo status=$?
|
51 | ## stdout: status=2
|
52 | ## BUG bash stdout: status=0
|
53 |
|
54 | #### -A function prints functions
|
55 | add () { expr 4 + 4; }
|
56 | div () { expr 6 / 2; }
|
57 | ek () { echo hello; }
|
58 | __ec () { echo hi; }
|
59 | _ab () { expr 10 % 3; }
|
60 | compgen -A function
|
61 | echo --
|
62 | compgen -A function _
|
63 | ## status: 0
|
64 | ## STDOUT:
|
65 | __ec
|
66 | _ab
|
67 | add
|
68 | div
|
69 | ek
|
70 | --
|
71 | __ec
|
72 | _ab
|
73 | ## END
|
74 |
|
75 | #### Invalid syntax
|
76 | compgen -A foo
|
77 | echo status=$?
|
78 | ## stdout: status=2
|
79 |
|
80 | #### how compgen calls completion functions
|
81 | foo_complete() {
|
82 | # first, cur, prev
|
83 | argv.py argv "$@"
|
84 | argv.py COMP_WORDS "${COMP_WORDS[@]}"
|
85 | argv.py COMP_CWORD "${COMP_CWORD}"
|
86 | argv.py COMP_LINE "${COMP_LINE}"
|
87 | argv.py COMP_POINT "${COMP_POINT}"
|
88 | #return 124
|
89 | COMPREPLY=(one two three)
|
90 | }
|
91 | compgen -F foo_complete foo a b c
|
92 | ## STDOUT:
|
93 | ['argv', 'compgen', 'foo', '']
|
94 | ['COMP_WORDS']
|
95 | ['COMP_CWORD', '-1']
|
96 | ['COMP_LINE', '']
|
97 | ['COMP_POINT', '0']
|
98 | one
|
99 | two
|
100 | three
|
101 | ## END
|
102 |
|
103 | #### complete -o -F (git)
|
104 | foo() { echo foo; }
|
105 | wrapper=foo
|
106 | complete -o default -o nospace -F $wrapper git
|
107 | ## status: 0
|
108 |
|
109 | #### compopt with invalid syntax
|
110 | compopt -o invalid
|
111 | echo status=$?
|
112 | ## stdout: status=2
|
113 |
|
114 | #### compopt fails when not in completion function
|
115 | # NOTE: Have to be executing a completion function
|
116 | compopt -o filenames +o nospace
|
117 | ## status: 1
|
118 |
|
119 | #### compgen -f on invalid dir
|
120 | compgen -f /non-existing-dir/
|
121 | ## status: 1
|
122 | ## stdout-json: ""
|
123 |
|
124 | #### compgen -f
|
125 | mkdir -p $TMP/compgen
|
126 | touch $TMP/compgen/{one,two,three}
|
127 | cd $TMP/compgen
|
128 | compgen -f | sort
|
129 | echo --
|
130 | compgen -f t | sort
|
131 | ## STDOUT:
|
132 | one
|
133 | three
|
134 | two
|
135 | --
|
136 | three
|
137 | two
|
138 | ## END
|
139 |
|
140 | #### compgen -v with local vars
|
141 | v1_global=0
|
142 | f() {
|
143 | local v2_local=0
|
144 | compgen -v v
|
145 | }
|
146 | f
|
147 | ## STDOUT:
|
148 | v1_global
|
149 | v2_local
|
150 | ## END
|
151 |
|
152 | #### compgen -v on unknown var
|
153 | compgen -v __nonexistent__
|
154 | ## status: 1
|
155 | ## stdout-json: ""
|
156 |
|
157 | #### compgen -v P
|
158 | cd > /dev/null # for some reason in bash, this makes PIPESTATUS appear!
|
159 | compgen -v P | grep -E '^PATH|PWD' | sort
|
160 | ## STDOUT:
|
161 | PATH
|
162 | PWD
|
163 | ## END
|
164 |
|
165 | #### compgen -e with global/local exported vars
|
166 | export v1_global=0
|
167 | f() {
|
168 | local v2_local=0
|
169 | export v2_local
|
170 | compgen -e v
|
171 | }
|
172 | f
|
173 | ## STDOUT:
|
174 | v1_global
|
175 | v2_local
|
176 | ## END
|
177 |
|
178 | #### compgen -e on known, but unexported, var
|
179 | unexported=0
|
180 | compgen -e unexported
|
181 | ## status: 1
|
182 | ## stdout-json: ""
|
183 |
|
184 | #### compgen -e on unknown var
|
185 | compgen -e __nonexistent__
|
186 | ## status: 1
|
187 | ## stdout-json: ""
|
188 |
|
189 | #### compgen -e P
|
190 | cd > /dev/null # for some reason in bash, this makes PIPESTATUS appear!
|
191 | compgen -e P | grep -E '^PATH|PWD' | sort
|
192 | ## STDOUT:
|
193 | PATH
|
194 | PWD
|
195 | ## END
|
196 |
|
197 | #### compgen with actions: function / variable / file
|
198 | mkdir -p $TMP/compgen2
|
199 | touch $TMP/compgen2/{PA,Q}_FILE
|
200 | cd $TMP/compgen2 # depends on previous test above!
|
201 | PA_FUNC() { echo P; }
|
202 | Q_FUNC() { echo Q; }
|
203 | compgen -A function -A variable -A file PA
|
204 | ## STDOUT:
|
205 | PA_FUNC
|
206 | PATH
|
207 | PA_FILE
|
208 | ## END
|
209 |
|
210 | #### compgen with actions: alias, setopt
|
211 | alias v_alias='ls'
|
212 | alias v_alias2='ls'
|
213 | alias a1='ls'
|
214 | compgen -A alias -A setopt v
|
215 | ## STDOUT:
|
216 | v_alias
|
217 | v_alias2
|
218 | verbose
|
219 | vi
|
220 | ## END
|
221 |
|
222 | #### compgen with actions: shopt
|
223 | compgen -A shopt -P [ -S ] nu
|
224 | ## STDOUT:
|
225 | [nullglob]
|
226 | ## END
|
227 |
|
228 | #### compgen with action and suffix: helptopic
|
229 | compgen -A helptopic -S ___ fal
|
230 | ## STDOUT:
|
231 | false___
|
232 | ## END
|
233 |
|
234 | #### compgen -A directory
|
235 | cd $REPO_ROOT
|
236 | compgen -A directory c | sort
|
237 | ## STDOUT:
|
238 | client
|
239 | core
|
240 | cpp
|
241 | ## END
|
242 |
|
243 | #### compgen -A file
|
244 | cd $REPO_ROOT
|
245 | compgen -A file o | sort
|
246 | ## STDOUT:
|
247 | oil-version.txt
|
248 | opy
|
249 | osh
|
250 | ## END
|
251 |
|
252 | #### compgen -A user
|
253 | # no assertion because this isn't hermetic
|
254 | compgen -A user
|
255 | ## status: 0
|
256 |
|
257 | #### compgen -A command completes external commands
|
258 | # NOTE: this test isn't hermetic
|
259 | compgen -A command xarg | uniq
|
260 | echo status=$?
|
261 | ## STDOUT:
|
262 | xargs
|
263 | status=0
|
264 | ## END
|
265 |
|
266 | #### compgen -A command completes functions and aliases
|
267 | our_func() { echo ; }
|
268 | our_func2() { echo ; }
|
269 | alias our_alias=foo
|
270 |
|
271 | compgen -A command our_
|
272 | echo status=$?
|
273 |
|
274 | # Introduce another function. Note that we're missing test coverage for
|
275 | # 'complete', i.e. bug #1064.
|
276 | our_func3() { echo ; }
|
277 |
|
278 | compgen -A command our_
|
279 | echo status=$?
|
280 |
|
281 | ## STDOUT:
|
282 | our_alias
|
283 | our_func
|
284 | our_func2
|
285 | status=0
|
286 | our_alias
|
287 | our_func
|
288 | our_func2
|
289 | our_func3
|
290 | status=0
|
291 | ## END
|
292 |
|
293 | #### compgen -A command completes builtins and keywords
|
294 | compgen -A command eva
|
295 | echo status=$?
|
296 | compgen -A command whil
|
297 | echo status=$?
|
298 | ## STDOUT:
|
299 | eval
|
300 | status=0
|
301 | while
|
302 | status=0
|
303 | ## END
|
304 |
|
305 | #### compgen -k by itself shows all reserved shell keywords
|
306 | compgen -k | grep -E '^(\!|\[\[|\]\]|case|coproc|do|done|elif|else|esac|fi|for|function|if|in|select|then|time|until|while|\{|\})$' | sort
|
307 | ## STDOUT:
|
308 | !
|
309 | [[
|
310 | ]]
|
311 | case
|
312 | coproc
|
313 | do
|
314 | done
|
315 | elif
|
316 | else
|
317 | esac
|
318 | fi
|
319 | for
|
320 | function
|
321 | if
|
322 | in
|
323 | select
|
324 | then
|
325 | time
|
326 | until
|
327 | while
|
328 | {
|
329 | }
|
330 | ## END
|
331 |
|
332 | #### compgen -k completes reserved shell keywords
|
333 | compgen -k do | sort
|
334 | echo status=$?
|
335 | compgen -k el | sort
|
336 | echo status=$?
|
337 | ## STDOUT:
|
338 | do
|
339 | done
|
340 | status=0
|
341 | elif
|
342 | else
|
343 | status=0
|
344 | ## END
|
345 |
|
346 | #### -o filenames and -o nospace have no effect with compgen
|
347 | # they are POSTPROCESSING.
|
348 | compgen -o filenames -o nospace -W 'bin build'
|
349 | ## STDOUT:
|
350 | bin
|
351 | build
|
352 | ## END
|
353 |
|
354 | #### -o plusdirs and -o dirnames with compgen
|
355 | cd $REPO_ROOT
|
356 | compgen -o plusdirs -W 'a b1 b2' b | sort
|
357 | echo ---
|
358 | compgen -o dirnames b | sort
|
359 | ## STDOUT:
|
360 | b1
|
361 | b2
|
362 | benchmarks
|
363 | bin
|
364 | build
|
365 | builtin
|
366 | ---
|
367 | benchmarks
|
368 | bin
|
369 | build
|
370 | builtin
|
371 | ## END
|
372 |
|
373 | #### compgen -o default completes files and dirs
|
374 | cd $REPO_ROOT
|
375 | compgen -o default spec/t | sort
|
376 | ## STDOUT:
|
377 | spec/testdata
|
378 | spec/tilde.test.sh
|
379 | spec/toysh-posix.test.sh
|
380 | spec/toysh.test.sh
|
381 | spec/type-compat.test.sh
|
382 | ## END
|
383 |
|
384 | #### compgen doesn't respect -X for user-defined functions
|
385 | # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
|
386 | # differently!
|
387 | case $SH in
|
388 | *bash|*osh)
|
389 | $SH --rcfile /dev/null -i -c '
|
390 | shopt -s extglob
|
391 | fun() {
|
392 | COMPREPLY=(one two three bin)
|
393 | }
|
394 | compgen -X "@(two|bin)" -F fun
|
395 | echo --
|
396 | compgen -X "!@(two|bin)" -F fun
|
397 | '
|
398 | esac
|
399 | ## STDOUT:
|
400 | one
|
401 | three
|
402 | --
|
403 | two
|
404 | bin
|
405 | ## END
|
406 |
|
407 | #### compgen -W words -X filter
|
408 | # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
|
409 | # differently!
|
410 | case $SH in
|
411 | *bash|*osh)
|
412 | $SH --rcfile /dev/null -i -c 'shopt -s extglob; compgen -X "@(two|bin)" -W "one two three bin"'
|
413 | esac
|
414 | ## STDOUT:
|
415 | one
|
416 | three
|
417 | ## END
|
418 |
|
419 | #### compgen -f -X filter -- $cur
|
420 | cd $TMP
|
421 | touch spam.py spam.sh
|
422 | compgen -f -- sp | sort
|
423 | echo --
|
424 | # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
|
425 | # differently!
|
426 | case $SH in
|
427 | *bash|*osh)
|
428 | $SH --rcfile /dev/null -i -c 'shopt -s extglob; compgen -f -X "!*.@(py)" -- sp'
|
429 | esac
|
430 | ## STDOUT:
|
431 | spam.py
|
432 | spam.sh
|
433 | --
|
434 | spam.py
|
435 | ## END
|
436 |
|
437 | #### compgen doesn't need shell quoting
|
438 | # There is an obsolete comment in bash_completion that claims the opposite.
|
439 | cd $TMP
|
440 | touch 'foo bar'
|
441 | touch "foo'bar"
|
442 | compgen -f "foo b"
|
443 | compgen -f "foo'"
|
444 | ## STDOUT:
|
445 | foo bar
|
446 | foo'bar
|
447 | ## END
|
448 |
|
449 | #### compgen -W 'one two three'
|
450 | cd $REPO_ROOT
|
451 | compgen -W 'one two three'
|
452 | echo --
|
453 | compgen -W 'w1 w2 three' -A directory w
|
454 | echo --
|
455 | compgen -A directory -W 'w1 w2 three' w # order doesn't matter
|
456 | ## STDOUT:
|
457 | one
|
458 | two
|
459 | three
|
460 | --
|
461 | web
|
462 | w1
|
463 | w2
|
464 | --
|
465 | web
|
466 | w1
|
467 | w2
|
468 | ## END
|
469 |
|
470 | #### compgen -W evaluates code in $()
|
471 | IFS=':%'
|
472 | compgen -W '$(echo "spam:eggs%ham cheese")'
|
473 | ## STDOUT:
|
474 | spam
|
475 | eggs
|
476 | ham cheese
|
477 | ## END
|
478 |
|
479 | #### compgen -W uses IFS, and delimiters are escaped with \
|
480 | IFS=':%'
|
481 | compgen -W 'spam:eggs%ham cheese\:colon'
|
482 | ## STDOUT:
|
483 | spam
|
484 | eggs
|
485 | ham cheese:colon
|
486 | ## END
|
487 |
|
488 | #### Parse errors for compgen -W and complete -W
|
489 | # bash doesn't detect as many errors because it lacks static parsing.
|
490 | compgen -W '${'
|
491 | echo status=$?
|
492 | complete -W '${' foo
|
493 | echo status=$?
|
494 | ## STDOUT:
|
495 | status=2
|
496 | status=2
|
497 | ## END
|
498 | ## BUG bash STDOUT:
|
499 | status=1
|
500 | status=0
|
501 | ## END
|
502 |
|
503 | #### Runtime errors for compgen -W
|
504 | compgen -W 'foo $(( 1 / 0 )) bar'
|
505 | echo status=$?
|
506 | ## STDOUT:
|
507 | status=1
|
508 | ## END
|
509 |
|
510 | #### Runtime errors for compgen -F func
|
511 | _foo() {
|
512 | COMPREPLY=( foo bar )
|
513 | COMPREPLY+=( $(( 1 / 0 )) ) # FATAL, but we still have candidates
|
514 | }
|
515 | compgen -F _foo foo
|
516 | echo status=$?
|
517 | ## STDOUT:
|
518 | status=1
|
519 | ## END
|
520 |
|
521 | #### compgen -W '' cmd is not a usage error
|
522 | # Bug fix due to '' being falsey in Python
|
523 | compgen -W '' -- foo
|
524 | echo status=$?
|
525 | ## stdout: status=1
|
526 |
|
527 | #### compgen -A builtin
|
528 | compgen -A builtin g
|
529 | ## STDOUT:
|
530 | getopts
|
531 | ## END
|
532 |
|
533 | #### complete -C vs. compgen -C
|
534 |
|
535 | f() { echo foo; echo bar; }
|
536 |
|
537 | # Bash prints warnings: -C option may not work as you expect
|
538 | # -F option may not work as you expect
|
539 | #
|
540 | # https://unix.stackexchange.com/questions/117987/compgen-warning-c-option-not-working-as-i-expected
|
541 | #
|
542 | # compexport fixes this problem, because it invokves ShellFuncAction, whcih
|
543 | # sets COMP_ARGV, COMP_WORDS, etc.
|
544 | #
|
545 | # Should we print a warning?
|
546 |
|
547 | compgen -C f b
|
548 | echo compgen=$?
|
549 |
|
550 | complete -C f b
|
551 | echo complete=$?
|
552 |
|
553 | ## STDOUT:
|
554 | foo
|
555 | bar
|
556 | compgen=0
|
557 | complete=0
|
558 | ## END
|