OILS / spec / builtin-completion.test.sh View on Github | oilshell.org

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