1 |
|
2 | ## oils_failures_allowed: 3
|
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 with actions: function / variable / file
|
166 | mkdir -p $TMP/compgen2
|
167 | touch $TMP/compgen2/{PA,Q}_FILE
|
168 | cd $TMP/compgen2 # depends on previous test above!
|
169 | PA_FUNC() { echo P; }
|
170 | Q_FUNC() { echo Q; }
|
171 | compgen -A function -A variable -A file PA
|
172 | ## STDOUT:
|
173 | PA_FUNC
|
174 | PATH
|
175 | PA_FILE
|
176 | ## END
|
177 |
|
178 | #### compgen with actions: alias, setopt
|
179 | alias v_alias='ls'
|
180 | alias v_alias2='ls'
|
181 | alias a1='ls'
|
182 | compgen -A alias -A setopt v
|
183 | ## STDOUT:
|
184 | v_alias
|
185 | v_alias2
|
186 | verbose
|
187 | vi
|
188 | ## END
|
189 |
|
190 | #### compgen with actions: shopt
|
191 | compgen -A shopt -P [ -S ] nu
|
192 | ## STDOUT:
|
193 | [nullglob]
|
194 | ## END
|
195 |
|
196 | #### compgen with action and suffix: helptopic
|
197 | compgen -A helptopic -S ___ fal
|
198 | ## STDOUT:
|
199 | false___
|
200 | ## END
|
201 |
|
202 | #### compgen -A directory
|
203 | cd $REPO_ROOT
|
204 | compgen -A directory c | sort
|
205 | ## STDOUT:
|
206 | client
|
207 | core
|
208 | cpp
|
209 | ## END
|
210 |
|
211 | #### compgen -A file
|
212 | cd $REPO_ROOT
|
213 | compgen -A file o | sort
|
214 | ## STDOUT:
|
215 | oil-version.txt
|
216 | opy
|
217 | osh
|
218 | ## END
|
219 |
|
220 | #### compgen -A user
|
221 | # no assertion because this isn't hermetic
|
222 | compgen -A user
|
223 | ## status: 0
|
224 |
|
225 | #### compgen -A command completes external commands
|
226 | # NOTE: this test isn't hermetic
|
227 | compgen -A command xarg | uniq
|
228 | echo status=$?
|
229 | ## STDOUT:
|
230 | xargs
|
231 | status=0
|
232 | ## END
|
233 |
|
234 | #### compgen -A command completes functions and aliases
|
235 | our_func() { echo ; }
|
236 | our_func2() { echo ; }
|
237 | alias our_alias=foo
|
238 |
|
239 | compgen -A command our_
|
240 | echo status=$?
|
241 |
|
242 | # Introduce another function. Note that we're missing test coverage for
|
243 | # 'complete', i.e. bug #1064.
|
244 | our_func3() { echo ; }
|
245 |
|
246 | compgen -A command our_
|
247 | echo status=$?
|
248 |
|
249 | ## STDOUT:
|
250 | our_alias
|
251 | our_func
|
252 | our_func2
|
253 | status=0
|
254 | our_alias
|
255 | our_func
|
256 | our_func2
|
257 | our_func3
|
258 | status=0
|
259 | ## END
|
260 |
|
261 | #### compgen -A command completes builtins and keywords
|
262 | compgen -A command eva
|
263 | echo status=$?
|
264 | compgen -A command whil
|
265 | echo status=$?
|
266 | ## STDOUT:
|
267 | eval
|
268 | status=0
|
269 | while
|
270 | status=0
|
271 | ## END
|
272 |
|
273 | #### -o filenames and -o nospace have no effect with compgen
|
274 | # they are POSTPROCESSING.
|
275 | compgen -o filenames -o nospace -W 'bin build'
|
276 | ## STDOUT:
|
277 | bin
|
278 | build
|
279 | ## END
|
280 |
|
281 | #### -o plusdirs and -o dirnames with compgen
|
282 | cd $REPO_ROOT
|
283 | compgen -o plusdirs -W 'a b1 b2' b | sort
|
284 | echo ---
|
285 | compgen -o dirnames b | sort
|
286 | ## STDOUT:
|
287 | b1
|
288 | b2
|
289 | benchmarks
|
290 | bin
|
291 | build
|
292 | builtin
|
293 | ---
|
294 | benchmarks
|
295 | bin
|
296 | build
|
297 | builtin
|
298 | ## END
|
299 |
|
300 | #### compgen -o default completes files and dirs
|
301 | cd $REPO_ROOT
|
302 | compgen -o default spec/t | sort
|
303 | ## STDOUT:
|
304 | spec/testdata
|
305 | spec/tilde.test.sh
|
306 | spec/toysh-posix.test.sh
|
307 | spec/toysh.test.sh
|
308 | spec/type-compat.test.sh
|
309 | ## END
|
310 |
|
311 | #### compgen doesn't respect -X for user-defined functions
|
312 | # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
|
313 | # differently!
|
314 | case $SH in
|
315 | *bash|*osh)
|
316 | $SH --rcfile /dev/null -i -c '
|
317 | shopt -s extglob
|
318 | fun() {
|
319 | COMPREPLY=(one two three bin)
|
320 | }
|
321 | compgen -X "@(two|bin)" -F fun
|
322 | echo --
|
323 | compgen -X "!@(two|bin)" -F fun
|
324 | '
|
325 | esac
|
326 | ## STDOUT:
|
327 | one
|
328 | three
|
329 | --
|
330 | two
|
331 | bin
|
332 | ## END
|
333 |
|
334 | #### compgen -W words -X filter
|
335 | # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
|
336 | # differently!
|
337 | case $SH in
|
338 | *bash|*osh)
|
339 | $SH --rcfile /dev/null -i -c 'shopt -s extglob; compgen -X "@(two|bin)" -W "one two three bin"'
|
340 | esac
|
341 | ## STDOUT:
|
342 | one
|
343 | three
|
344 | ## END
|
345 |
|
346 | #### compgen -f -X filter -- $cur
|
347 | cd $TMP
|
348 | touch spam.py spam.sh
|
349 | compgen -f -- sp | sort
|
350 | echo --
|
351 | # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
|
352 | # differently!
|
353 | case $SH in
|
354 | *bash|*osh)
|
355 | $SH --rcfile /dev/null -i -c 'shopt -s extglob; compgen -f -X "!*.@(py)" -- sp'
|
356 | esac
|
357 | ## STDOUT:
|
358 | spam.py
|
359 | spam.sh
|
360 | --
|
361 | spam.py
|
362 | ## END
|
363 |
|
364 | #### compgen doesn't need shell quoting
|
365 | # There is an obsolete comment in bash_completion that claims the opposite.
|
366 | cd $TMP
|
367 | touch 'foo bar'
|
368 | touch "foo'bar"
|
369 | compgen -f "foo b"
|
370 | compgen -f "foo'"
|
371 | ## STDOUT:
|
372 | foo bar
|
373 | foo'bar
|
374 | ## END
|
375 |
|
376 | #### compgen -W 'one two three'
|
377 | cd $REPO_ROOT
|
378 | compgen -W 'one two three'
|
379 | echo --
|
380 | compgen -W 'w1 w2 three' -A directory w
|
381 | echo --
|
382 | compgen -A directory -W 'w1 w2 three' w # order doesn't matter
|
383 | ## STDOUT:
|
384 | one
|
385 | two
|
386 | three
|
387 | --
|
388 | web
|
389 | w1
|
390 | w2
|
391 | --
|
392 | web
|
393 | w1
|
394 | w2
|
395 | ## END
|
396 |
|
397 | #### compgen -W evaluates code in $()
|
398 | IFS=':%'
|
399 | compgen -W '$(echo "spam:eggs%ham cheese")'
|
400 | ## STDOUT:
|
401 | spam
|
402 | eggs
|
403 | ham cheese
|
404 | ## END
|
405 |
|
406 | #### compgen -W uses IFS, and delimiters are escaped with \
|
407 | IFS=':%'
|
408 | compgen -W 'spam:eggs%ham cheese\:colon'
|
409 | ## STDOUT:
|
410 | spam
|
411 | eggs
|
412 | ham cheese:colon
|
413 | ## END
|
414 |
|
415 | #### Parse errors for compgen -W and complete -W
|
416 | # bash doesn't detect as many errors because it lacks static parsing.
|
417 | compgen -W '${'
|
418 | echo status=$?
|
419 | complete -W '${' foo
|
420 | echo status=$?
|
421 | ## STDOUT:
|
422 | status=2
|
423 | status=2
|
424 | ## END
|
425 | ## BUG bash STDOUT:
|
426 | status=1
|
427 | status=0
|
428 | ## END
|
429 |
|
430 | #### Runtime errors for compgen -W
|
431 | compgen -W 'foo $(( 1 / 0 )) bar'
|
432 | echo status=$?
|
433 | ## STDOUT:
|
434 | status=1
|
435 | ## END
|
436 |
|
437 | #### Runtime errors for compgen -F func
|
438 | _foo() {
|
439 | COMPREPLY=( foo bar )
|
440 | COMPREPLY+=( $(( 1 / 0 )) ) # FATAL, but we still have candidates
|
441 | }
|
442 | compgen -F _foo foo
|
443 | echo status=$?
|
444 | ## STDOUT:
|
445 | status=1
|
446 | ## END
|
447 |
|
448 | #### compgen -W '' cmd is not a usage error
|
449 | # Bug fix due to '' being falsey in Python
|
450 | compgen -W '' -- foo
|
451 | echo status=$?
|
452 | ## stdout: status=1
|
453 |
|
454 | #### compgen -A builtin
|
455 | compgen -A builtin g
|
456 | ## STDOUT:
|
457 | getopts
|
458 | ## END
|
459 |
|
460 | #### complete -C vs. compgen -C
|
461 |
|
462 | f() { echo foo; echo bar; }
|
463 |
|
464 | # Bash prints warnings: -C option may not work as you expect
|
465 | # -F option may not work as you expect
|
466 | #
|
467 | # https://unix.stackexchange.com/questions/117987/compgen-warning-c-option-not-working-as-i-expected
|
468 | #
|
469 | # compexport fixes this problem, because it invokves ShellFuncAction, whcih
|
470 | # sets COMP_ARGV, COMP_WORDS, etc.
|
471 | #
|
472 | # Should we print a warning?
|
473 |
|
474 | compgen -C f b
|
475 | echo compgen=$?
|
476 |
|
477 | complete -C f b
|
478 | echo complete=$?
|
479 |
|
480 | ## STDOUT:
|
481 | foo
|
482 | bar
|
483 | compgen=0
|
484 | complete=0
|
485 | ## END
|