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 pea
156 pgen-native
157 pgen2
158 py-yajl
159 pylib
160 ## END
161
162 #### compgen -A file
163 cd $REPO_ROOT
164 compgen -A file o | sort
165 ## STDOUT:
166 oil-version.txt
167 oil_lang
168 opy
169 osh
170 ## END
171
172 #### compgen -A user
173 # no assertion because this isn't hermetic
174 compgen -A user
175 ## status: 0
176
177 #### compgen -A command completes external commands
178 # NOTE: this test isn't hermetic
179 compgen -A command xarg | uniq
180 echo status=$?
181 ## STDOUT:
182 xargs
183 status=0
184 ## END
185
186 #### compgen -A command completes functions and aliases
187 our_func() { echo ; }
188 our_func2() { echo ; }
189 alias our_alias=foo
190
191 compgen -A command our_
192 echo status=$?
193
194 # Introduce another function. Note that we're missing test coverage for
195 # 'complete', i.e. bug #1064.
196 our_func3() { echo ; }
197
198 compgen -A command our_
199 echo status=$?
200
201 ## STDOUT:
202 our_alias
203 our_func
204 our_func2
205 status=0
206 our_alias
207 our_func
208 our_func2
209 our_func3
210 status=0
211 ## END
212
213 #### compgen -A command completes builtins and keywords
214 compgen -A command eva
215 echo status=$?
216 compgen -A command whil
217 echo status=$?
218 ## STDOUT:
219 eval
220 status=0
221 while
222 status=0
223 ## END
224
225 #### complete with nonexistent function
226 complete -F invalidZZ -D
227 echo status=$?
228 ## stdout: status=2
229 ## BUG bash stdout: status=0
230
231 #### complete with no action
232 complete foo
233 echo status=$?
234 ## stdout: status=2
235 ## BUG bash stdout: status=0
236
237 #### -o filenames and -o nospace have no effect with compgen
238 # they are POSTPROCESSING.
239 compgen -o filenames -o nospace -W 'bin build'
240 ## STDOUT:
241 bin
242 build
243 ## END
244
245 #### -o plusdirs and -o dirnames with compgen
246 cd $REPO_ROOT
247 compgen -o plusdirs -W 'a b1 b2' b | sort
248 echo ---
249 compgen -o dirnames b | sort
250 ## STDOUT:
251 b1
252 b2
253 benchmarks
254 bin
255 build
256 ---
257 benchmarks
258 bin
259 build
260 ## END
261
262 #### compgen -o default completes files and dirs
263 cd $REPO_ROOT
264 compgen -o default spec/t | sort
265 ## STDOUT:
266 spec/tea-func.test.sh
267 spec/testdata
268 spec/tilde.test.sh
269 spec/toysh-posix.test.sh
270 spec/toysh.test.sh
271 spec/type-compat.test.sh
272 ## END
273
274 #### compgen doesn't respect -X for user-defined functions
275 # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
276 # differently!
277 case $SH in
278 *bash|*osh)
279 $SH --rcfile /dev/null -i -c '
280 shopt -s extglob
281 fun() {
282 COMPREPLY=(one two three bin)
283 }
284 compgen -X "@(two|bin)" -F fun
285 echo --
286 compgen -X "!@(two|bin)" -F fun
287 '
288 esac
289 ## STDOUT:
290 one
291 three
292 --
293 two
294 bin
295 ## END
296
297 #### compgen -W words -X filter
298 # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
299 # differently!
300 case $SH in
301 *bash|*osh)
302 $SH --rcfile /dev/null -i -c 'shopt -s extglob; compgen -X "@(two|bin)" -W "one two three bin"'
303 esac
304 ## STDOUT:
305 one
306 three
307 ## END
308
309 #### compgen -f -X filter -- $cur
310 cd $TMP
311 touch spam.py spam.sh
312 compgen -f -- sp | sort
313 echo --
314 # WORKAROUND: wrap in bash -i -c because non-interactive bash behaves
315 # differently!
316 case $SH in
317 *bash|*osh)
318 $SH --rcfile /dev/null -i -c 'shopt -s extglob; compgen -f -X "!*.@(py)" -- sp'
319 esac
320 ## STDOUT:
321 spam.py
322 spam.sh
323 --
324 spam.py
325 ## END
326
327 #### compgen doesn't need shell quoting
328 # There is an obsolete comment in bash_completion that claims the opposite.
329 cd $TMP
330 touch 'foo bar'
331 touch "foo'bar"
332 compgen -f "foo b"
333 compgen -f "foo'"
334 ## STDOUT:
335 foo bar
336 foo'bar
337 ## END
338
339 #### compgen -W 'one two three'
340 cd $REPO_ROOT
341 compgen -W 'one two three'
342 echo --
343 compgen -W 'w1 w2 three' -A directory w
344 echo --
345 compgen -A directory -W 'w1 w2 three' w # order doesn't matter
346 ## STDOUT:
347 one
348 two
349 three
350 --
351 web
352 w1
353 w2
354 --
355 web
356 w1
357 w2
358 ## END
359
360 #### compgen -W evaluates code in $()
361 IFS=':%'
362 compgen -W '$(echo "spam:eggs%ham cheese")'
363 ## STDOUT:
364 spam
365 eggs
366 ham cheese
367 ## END
368
369 #### compgen -W uses IFS, and delimiters are escaped with \
370 IFS=':%'
371 compgen -W 'spam:eggs%ham cheese\:colon'
372 ## STDOUT:
373 spam
374 eggs
375 ham cheese:colon
376 ## END
377
378 #### Parse errors for compgen -W and complete -W
379 # bash doesn't detect as many errors because it lacks static parsing.
380 compgen -W '${'
381 echo status=$?
382 complete -W '${' foo
383 echo status=$?
384 ## STDOUT:
385 status=2
386 status=2
387 ## END
388 ## BUG bash STDOUT:
389 status=1
390 status=0
391 ## END
392
393 #### Runtime errors for compgen -W
394 compgen -W 'foo $(( 1 / 0 )) bar'
395 echo status=$?
396 ## STDOUT:
397 status=1
398 ## END
399
400 #### Runtime errors for compgen -F func
401 _foo() {
402 COMPREPLY=( foo bar )
403 COMPREPLY+=( $(( 1 / 0 )) ) # FATAL, but we still have candidates
404 }
405 compgen -F _foo foo
406 echo status=$?
407 ## STDOUT:
408 status=1
409 ## END
410
411 #### compgen -W '' cmd is not a usage error
412 # Bug fix due to '' being falsey in Python
413 compgen -W '' -- foo
414 echo status=$?
415 ## stdout: status=1