1
2 #### -A function prints functions
3 add () { expr 4 + 4; }
4 div () { expr 6 / 2; }
5 ek () { echo hello; }
6 __ec () { echo hi; }
7 _ab () { expr 10 % 3; }
8 compgen -A function
9 echo --
10 compgen -A function _
11 ## status: 0
12 ## STDOUT:
13 __ec
14 _ab
15 add
16 div
17 ek
18 --
19 __ec
20 _ab
21 ## END
22
23 #### Invalid syntax
24 compgen -A foo
25 echo status=$?
26 ## stdout: status=2
27
28 #### how compgen calls completion functions
29 foo_complete() {
30 # first, cur, prev
31 argv.py argv "$@"
32 argv.py COMP_WORDS "${COMP_WORDS[@]}"
33 argv.py COMP_CWORD "${COMP_CWORD}"
34 argv.py COMP_LINE "${COMP_LINE}"
35 argv.py COMP_POINT "${COMP_POINT}"
36 #return 124
37 COMPREPLY=(one two three)
38 }
39 compgen -F foo_complete foo a b c
40 ## STDOUT:
41 ['argv', 'compgen', 'foo', '']
42 ['COMP_WORDS']
43 ['COMP_CWORD', '-1']
44 ['COMP_LINE', '']
45 ['COMP_POINT', '0']
46 one
47 two
48 three
49 ## END
50
51 #### complete -o -F (git)
52 foo() { echo foo; }
53 wrapper=foo
54 complete -o default -o nospace -F $wrapper git
55 ## status: 0
56
57 #### compopt with invalid syntax
58 compopt -o invalid
59 echo status=$?
60 ## stdout: status=2
61
62 #### compopt fails when not in completion function
63 # NOTE: Have to be executing a completion function
64 compopt -o filenames +o nospace
65 ## status: 1
66
67 #### compgen -f on invalid dir
68 compgen -f /non-existing-dir/
69 ## status: 1
70 ## stdout-json: ""
71
72 #### compgen -f
73 mkdir -p $TMP/compgen
74 touch $TMP/compgen/{one,two,three}
75 cd $TMP/compgen
76 compgen -f | sort
77 echo --
78 compgen -f t | sort
79 ## STDOUT:
80 one
81 three
82 two
83 --
84 three
85 two
86 ## END
87
88 #### compgen -v with local vars
89 v1_global=0
90 f() {
91 local v2_local=0
92 compgen -v v
93 }
94 f
95 ## STDOUT:
96 v1_global
97 v2_local
98 ## END
99
100 #### compgen -v on unknown var
101 compgen -v __nonexistent__
102 ## status: 1
103 ## stdout-json: ""
104
105 #### compgen -v P
106 cd > /dev/null # for some reason in bash, this makes PIPESTATUS appear!
107 compgen -v P | grep -E '^PATH|PWD' | sort
108 ## STDOUT:
109 PATH
110 PWD
111 ## END
112
113 #### compgen with actions: function / variable / file
114 mkdir -p $TMP/compgen2
115 touch $TMP/compgen2/{PA,Q}_FILE
116 cd $TMP/compgen2 # depends on previous test above!
117 PA_FUNC() { echo P; }
118 Q_FUNC() { echo Q; }
119 compgen -A function -A variable -A file PA
120 ## STDOUT:
121 PA_FUNC
122 PATH
123 PA_FILE
124 ## END
125
126 #### compgen with actions: alias, setopt
127 alias v_alias='ls'
128 alias v_alias2='ls'
129 alias a1='ls'
130 compgen -A alias -A setopt v
131 ## STDOUT:
132 v_alias
133 v_alias2
134 verbose
135 vi
136 ## END
137
138 #### compgen with actions: shopt
139 compgen -A shopt -P [ -S ] nu
140 ## STDOUT:
141 [nullglob]
142 ## END
143
144 #### compgen with action and suffix: helptopic
145 compgen -A helptopic -S ___ fa
146 ## STDOUT:
147 false___
148 ## END
149
150 #### compgen -A directory
151 # omit portable-files.mk
152 cd $REPO_ROOT
153 compgen -A directory p | sort
154 ## STDOUT:
155 pgen-native
156 pgen2
157 py-yajl
158 pylib
159 ## END
160
161 #### compgen -A file
162 cd $REPO_ROOT
163 compgen -A file o | sort
164 ## STDOUT:
165 oil-version.txt
166 oil_lang
167 opy
168 osh
169 ## END
170
171 #### compgen -A user
172 # no assertion because this isn't hermetic
173 compgen -A user
174 ## status: 0
175
176 #### compgen -A command completes external commands
177 # NOTE: this test isn't hermetic
178 compgen -A command xarg | uniq
179 echo status=$?
180 ## STDOUT:
181 xargs
182 status=0
183 ## END
184
185 #### compgen -A command completes functions and aliases
186 our_func() { echo ; }
187 our_func2() { echo ; }
188 alias our_alias=foo
189
190 compgen -A command our_
191 echo status=$?
192
193 # Introduce another function. Note that we're missing test coverage for
194 # 'complete', i.e. bug #1064.
195 our_func3() { echo ; }
196
197 compgen -A command our_
198 echo status=$?
199
200 ## STDOUT:
201 our_alias
202 our_func
203 our_func2
204 status=0
205 our_alias
206 our_func
207 our_func2
208 our_func3
209 status=0
210 ## END
211
212 #### compgen -A command completes builtins and keywords
213 compgen -A command eva
214 echo status=$?
215 compgen -A command whil
216 echo status=$?
217 ## STDOUT:
218 eval
219 status=0
220 while
221 status=0
222 ## END
223
224 #### complete with nonexistent function
225 complete -F invalidZZ -D
226 echo status=$?
227 ## stdout: status=2
228 ## BUG bash stdout: status=0
229
230 #### complete with no action
231 complete foo
232 echo status=$?
233 ## stdout: status=2
234 ## BUG bash stdout: status=0
235
236 #### -o filenames and -o nospace have no effect with compgen
237 # they are POSTPROCESSING.
238 compgen -o filenames -o nospace -W 'bin build'
239 ## STDOUT:
240 bin
241 build
242 ## END
243
244 #### -o plusdirs and -o dirnames with compgen
245 cd $REPO_ROOT
246 compgen -o plusdirs -W 'a b1 b2' b | sort
247 echo ---
248 compgen -o dirnames b | sort
249 ## STDOUT:
250 b1
251 b2
252 benchmarks
253 bin
254 build
255 ---
256 benchmarks
257 bin
258 build
259 ## END
260
261 #### compgen -o default completes files and dirs
262 cd $REPO_ROOT
263 compgen -o default spec/t | sort
264 ## STDOUT:
265 spec/tea-func.test.sh
266 spec/testdata
267 spec/tilde.test.sh
268 spec/toysh-posix.test.sh
269 spec/toysh.test.sh
270 spec/type-compat.test.sh
271 ## END
272
273 #### compgen doesn't respect -X for user-defined functions
274 # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
275 # differently!
276 case $SH in
277 *bash|*osh)
278 $SH --rcfile /dev/null -i -c '
279 shopt -s extglob
280 fun() {
281 COMPREPLY=(one two three bin)
282 }
283 compgen -X "@(two|bin)" -F fun
284 echo --
285 compgen -X "!@(two|bin)" -F fun
286 '
287 esac
288 ## STDOUT:
289 one
290 three
291 --
292 two
293 bin
294 ## END
295
296 #### compgen -W words -X filter
297 # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
298 # differently!
299 case $SH in
300 *bash|*osh)
301 $SH --rcfile /dev/null -i -c 'shopt -s extglob; compgen -X "@(two|bin)" -W "one two three bin"'
302 esac
303 ## STDOUT:
304 one
305 three
306 ## END
307
308 #### compgen -f -X filter -- $cur
309 cd $TMP
310 touch spam.py spam.sh
311 compgen -f -- sp | sort
312 echo --
313 # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
314 # differently!
315 case $SH in
316 *bash|*osh)
317 $SH --rcfile /dev/null -i -c 'shopt -s extglob; compgen -f -X "!*.@(py)" -- sp'
318 esac
319 ## STDOUT:
320 spam.py
321 spam.sh
322 --
323 spam.py
324 ## END
325
326 #### compgen doesn't need shell quoting
327 # There is an obsolete comment in bash_completion that claims the opposite.
328 cd $TMP
329 touch 'foo bar'
330 touch "foo'bar"
331 compgen -f "foo b"
332 compgen -f "foo'"
333 ## STDOUT:
334 foo bar
335 foo'bar
336 ## END
337
338 #### compgen -W 'one two three'
339 cd $REPO_ROOT
340 compgen -W 'one two three'
341 echo --
342 compgen -W 'w1 w2 three' -A directory w
343 echo --
344 compgen -A directory -W 'w1 w2 three' w # order doesn't matter
345 ## STDOUT:
346 one
347 two
348 three
349 --
350 web
351 w1
352 w2
353 --
354 web
355 w1
356 w2
357 ## END
358
359 #### compgen -W evaluates code in $()
360 IFS=':%'
361 compgen -W '$(echo "spam:eggs%ham cheese")'
362 ## STDOUT:
363 spam
364 eggs
365 ham cheese
366 ## END
367
368 #### compgen -W uses IFS, and delimiters are escaped with \
369 IFS=':%'
370 compgen -W 'spam:eggs%ham cheese\:colon'
371 ## STDOUT:
372 spam
373 eggs
374 ham cheese:colon
375 ## END
376
377 #### Parse errors for compgen -W and complete -W
378 # bash doesn't detect as many errors because it lacks static parsing.
379 compgen -W '${'
380 echo status=$?
381 complete -W '${' foo
382 echo status=$?
383 ## STDOUT:
384 status=2
385 status=2
386 ## END
387 ## BUG bash STDOUT:
388 status=1
389 status=0
390 ## END
391
392 #### Runtime errors for compgen -W
393 compgen -W 'foo $(( 1 / 0 )) bar'
394 echo status=$?
395 ## STDOUT:
396 status=1
397 ## END
398
399 #### Runtime errors for compgen -F func
400 _foo() {
401 COMPREPLY=( foo bar )
402 COMPREPLY+=( $(( 1 / 0 )) ) # FATAL, but we still have candidates
403 }
404 compgen -F _foo foo
405 echo status=$?
406 ## STDOUT:
407 status=1
408 ## END
409
410 #### compgen -W '' cmd is not a usage error
411 # Bug fix due to '' being falsey in Python
412 compgen -W '' -- foo
413 echo status=$?
414 ## stdout: status=1