Improve __reassemble_comp_words_by_ref() (Alioth #313057)

Prohibit word creation of characters if they're excluded from
$COMP_WORDBREAKS.  For example, with ':' included in $COMP_WORDBREAKS,
'a b:' should split to 'b' and ':'.  With ':' excluded from
$COMP_WORDBREAKS, 'a b:' should split to 'b:', NOT 'b' and ':'.
This commit is contained in:
Freddy Vulto 2011-03-24 00:00:58 +01:00
parent 2c78ae3ea1
commit 8227e76e09
3 changed files with 65 additions and 7 deletions

View File

@ -14,6 +14,10 @@ bash-completion (2.x)
* If _filedir 'ext' returns nothing, just fallback to generic
file completion. Patch by Clint Byrum (Debian: #619014, LP: #533985)
[ Freddy Vulto ]
* Improve __reassemble_comp_words_by_ref() to not create words of
characters-to-exclude (Alioth: #313057)
-- David Paleino <d.paleino@gmail.com> Sun, 06 Feb 2011 21:46:37 +0100
bash-completion (1.3)

View File

@ -277,7 +277,7 @@ _upvars() {
# @param $3 cword Name of variable to return cword to
#
__reassemble_comp_words_by_ref() {
local exclude i j ref
local exclude i j line ref
# Exclude word separator characters?
if [[ $1 ]]; then
# Yes, exclude word separator characters;
@ -290,26 +290,40 @@ __reassemble_comp_words_by_ref() {
# Are characters excluded which were former included?
if [[ $exclude ]]; then
# Yes, list of word completion separators has shrunk;
line=$COMP_LINE
# Re-assemble words to complete
for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
# Is current word not word 0 (the command itself) and is word not
# empty and is word made up of just word separator characters to be
# excluded?
# empty and is word made up of just word separator characters to
# be excluded and is current word not preceded by whitespace in
# original line?
while [[ $i -gt 0 && ${COMP_WORDS[$i]} &&
${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]}
${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]}
]]; do
[ $j -ge 2 ] && ((j--))
# Append word separator to current word
# Is word separator not preceded by whitespace in original line
# and are we not going to append to word 0 (the command
# itself), then append to current word.
[[ ${line:0:1} != ' ' && ${line:0:1} != $'\t' ]] &&
(( j >= 2 )) && ((j--))
# Append word separator to current or new word
ref="$2[$j]"
eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
# Indicate new cword
[ $i = $COMP_CWORD ] && eval $3=$j
# Indicate next word if available, else end *both* while and for loop
# Remove whitespace (optional) + word separator from line copy
line=${line#*${COMP_WORDS[$i]}}
# Start new word if word separator in original line is
# followed by whitespace.
[[ ${line:0:1} == ' ' || ${line:0:1} == $'\t' ]] && ((j++))
# Indicate next word if available, else end *both* while and
# for loop
(( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
done
# Append word to current word
ref="$2[$j]"
eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
# Remove whitespace (optional) + word from line copy
line=${line#*${COMP_WORDS[i]}}
# Indicate new cword
[[ $i == $COMP_CWORD ]] && eval $3=$j
done

View File

@ -398,4 +398,44 @@ assert_bash_list {"b a a b 1"} $cmd $test
sync_after_int
set test {a b : c| with WORDBREAKS -= :}; # | = cursor position
set cmd {COMP_WORDS=(a b : c); COMP_CWORD=3; COMP_LINE='a b : c'; COMP_POINT=7}
assert_bash_exec $cmd $test
set cmd {_get_comp_words_by_ref -n : words; echo "${words[@]}"}
assert_bash_list {"a b : c"} $cmd $test
sync_after_int
set test {a b: c| with WORDBREAKS -= :}; # | = cursor position
if {[lindex $::BASH_VERSINFO 0] <= 3} {
set cmd {COMP_WORDS=(a b: c); COMP_CWORD=2}
} else {
set cmd {COMP_WORDS=(a b : c); COMP_CWORD=3}
}
append cmd {; COMP_LINE='a b: c'; COMP_POINT=6}
assert_bash_exec $cmd $test
set cmd {_get_comp_words_by_ref -n : words; echo "${words[@]}"}
assert_bash_list {"a b: c"} $cmd $test
sync_after_int
set test {a b :c| with WORDBREAKS -= :}; # | = cursor position
if {[lindex $::BASH_VERSINFO 0] <= 3} {
set cmd {COMP_WORDS=(a b :c); COMP_CWORD=2}
} else {
set cmd {COMP_WORDS=(a b : c); COMP_CWORD=3}
}
append cmd {; COMP_LINE='a b :c'; COMP_POINT=6}
assert_bash_exec $cmd $test
set cmd {_get_comp_words_by_ref -n : words; echo "${words[@]}"}
assert_bash_list {"a b :c"} $cmd $test
sync_after_int
teardown