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