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

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