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