[Bash-completion-devel] bash completion fails if shopt "nullglob" is set, repro info follows

C. Alex. North-Keys erlkonig at talisman.org
Tue Dec 20 10:49:57 UTC 2011


Bash autocompletions fails in many case when "shopt -s nullglob" has 
been run.

User visibility:

Anyone using shopt -s nullglob, the entire autocompletion is horribly 
broken, essentially useless in many contexts, along with the resulting 
frustration.  X users sometimes are shielded from the problem if the 
subshells spawned in xterms - which aren't login shells - are skipping 
the read of /etc/bash_completion .

Reproduction:

root at yggdrasil:~# cd ; mkdir tmp && cd tmp && touch aa bb cc
root at yggdrasil:~/tmp# less bb ^C
root at yggdrasil:~/tmp# # input was "less b<tab>", autocompleted, 
"<control-c>"
root at yggdrasil:~/tmp# shopt -s nullglob
root at yggdrasil:~/tmp# less b
aa  bb  cc
root at yggdrasil:~/tmp# # input was "less b<tab><tab>", autocompletion failed.

Running a trace with set -x shows trouble in 
__reassemble_comp_words_by_ref for starters, a function from 
/etc/bash_completion, which crumbles fairly early, to wit:

with shopt -u nullglob:

+ _get_comp_words_by_ref -n = cur prev
+ local exclude flag i OPTIND=1
+ words=()
+ local cur cword words
+ upargs=()
+ upvars=()
+ local upargs upvars vcur vcword vprev vwords
+ getopts c:i:n:p:w: flag -n = cur prev
+ case $flag in
+ exclude==
+ getopts c:i:n:p:w: flag -n = cur prev
+ [[ 4 -ge 3 ]]
+ case ${!OPTIND} in
+ vcur=cur
+ let 'OPTIND += 1'
+ [[ 4 -ge 4 ]]
+ case ${!OPTIND} in
+ vprev=prev
+ let 'OPTIND += 1'
+ [[ 4 -ge 5 ]]
+ __get_cword_at_cursor_by_ref = words cword cur
+ words=()
+ local cword words
+ __reassemble_comp_words_by_ref = words cword
+ local exclude i j ref
+ [[ -n = ]]
+ exclude==
+ eval cword=1
++ cword=1
+ [[ -n = ]]
+ (( i=0, j=0 ))
+ (( i < 2 ))
+ [[ 0 -gt 0 ]]
+ ref='words[0]'

with shopt -u nullglob it continues with:

+ eval 'words[0]=${!ref}${COMP_WORDS[i]}'
++ words[0]=less
+ [[ 0 == 1 ]]

but with shopt -s nullglob we see:

+ eval
+ [[ 0 == 1 ]]

the source is in /etc/bash_completion

     309             done
     310             # Append word to current word
     311             ref="$2[$j]"
 >  312             eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
     313             # Indicate new cword
     314             [[ $i == $COMP_CWORD ]] && eval $3=$j

At this point, on the second iteration of the surrounding loop,  $2 == 
words, $j == 0, and words[0] == less (if nullglob is off) or is unset 
(if nullglob is on).




More information about the Bash-completion-devel mailing list