[Bash-completion-commits] [SCM] bash-completion branch, master, updated. c9c98da36edeb9305e24e7ea2d8ccf8b0934ce70
Freddy Vulto
fvulto at gmail.com
Thu Dec 24 09:02:59 UTC 2009
The following commit has been merged in the master branch:
commit c9c98da36edeb9305e24e7ea2d8ccf8b0934ce70
Author: Freddy Vulto <fvulto at gmail.com>
Date: Thu Dec 24 10:00:29 2009 +0100
Fixed `quote_readline'.
This fixes completing filenames containing single quote (') on bash-4.
Also added emulation of `-o filenames' to _filedir.
Added tests for _filedir.
Fixed array assignment within __reassemble_comp_words_by_ref().
diff --git a/bash_completion b/bash_completion
index 1b103d7..d6374f7 100644
--- a/bash_completion
+++ b/bash_completion
@@ -188,19 +188,14 @@ quote()
echo \'${1//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
}
-# This function quotes the argument in a way so that readline dequoting
-# results in the original argument
+# @see _quote_readline_by_ref()
quote_readline()
{
- if [ ${BASH_VERSINFO[0]} -ge 4 ]; then
- # This function isn't really necessary on bash 4
- # See: http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
- echo "${1}"
- return
- fi
- local t="${1//\\/\\\\}"
- echo \'${t//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
-}
+ local quoted
+ _quote_readline_by_ref "$1" ret
+ printf %s "$ret"
+} # quote_readline()
+
# This function shell-dequotes the argument
dequote()
@@ -224,8 +219,6 @@ __reassemble_comp_words_by_ref() {
if [[ $1 ]]; then
# Yes, exclude word separator characters;
# Exclude only those characters, which were really included
- # NOTE: On bash-3, `COMP_WORDBREAKS' is empty which is ok; no
- # additional word breaking is done on bash-3.
exclude="${1//[^$COMP_WORDBREAKS]}"
fi
@@ -240,7 +233,7 @@ __reassemble_comp_words_by_ref() {
[ $j -ge 2 ] && ((j--))
# Append word separator to current word
ref="$2[$j]"
- eval $2[$j]=\""${!ref}${COMP_WORDS[$i]}"\"
+ 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
@@ -248,7 +241,7 @@ __reassemble_comp_words_by_ref() {
done
# Append word to current word
ref="$2[$j]"
- eval $2[$j]=\""${!ref}${COMP_WORDS[$i]}"\"
+ eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
# Indicate new cword
[ $i = $COMP_CWORD ] && eval $3=$j
done
@@ -295,7 +288,7 @@ _get_cword()
"${#cur}" -ge ${#words[i]} &&
# $cur doesn't match cword?
"${cur:0:${#words[i]}}" != "${words[i]}"
- ]]; do
+ ]]; do
# Strip first character
cur="${cur:1}"
# Decrease cursor position
@@ -369,6 +362,46 @@ __ltrim_colon_completions() {
} # __ltrim_colon_completions()
+# This function quotes the argument in a way so that readline dequoting
+# results in the original argument. This is necessary for at least
+# `compgen' which requires its arguments quoted/escaped:
+#
+# $ ls "a'b/"
+# c
+# $ compgen -f "a'b/" # Wrong, doesn't return output
+# $ compgen -f "a\'b/" # Good (bash-4)
+# a\'b/c
+# $ compgen -f "a\\\\\'b/" # Good (bash-3)
+# a\'b/c
+#
+# See also: http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
+# @param $1 Argument to quote
+# @param $2 Name of variable to return result to
+_quote_readline_by_ref()
+{
+ # If bash <= 3 and argument starts with single quote ('), double-escape
+# if [[ ${BASH_VERSINFO[0]} -le 3 && ${1:0:1} == "'" ]]; then
+# local t
+# printf -v t %q "${1:1}"
+# printf -v $2 %q "$t"
+# else
+# printf -v $2 %q "$1"
+# fi
+ if [[ ${1:0:1} == "'" ]]; then
+ # Quote word, leaving out first character
+ printf -v $2 %q "${1:1}"
+ if [[ ${BASH_VERSINFO[0]} -le 3 ]]; then
+ # Double-quote word on bash-3
+ printf -v $2 %q ${!2}
+ fi
+ elif [[ ${BASH_VERSINFO[0]} -le 3 && ${1:0:1} == '"' ]]; then
+ printf -v $2 %q "${1:1}"
+ else
+ printf -v $2 %q "$1"
+ fi
+} # _quote_readline_by_ref()
+
+
# This function performs file and directory completion. It's better than
# simply using 'compgen -f', because it honours spaces in filenames.
# If passed -d, it completes only on directories. If passed anything else,
@@ -376,12 +409,12 @@ __ltrim_colon_completions() {
#
_filedir()
{
- local IFS=$'\t\n' xspec
+ local i IFS=$'\t\n' xspec
- _expand || return 0
+ __expand_tilde_by_ref cur
local -a toks
- local tmp
+ local quoted tmp
# TODO: I've removed a "[ -n $tmp ] &&" before `printf '%s\n' $tmp',
# and everything works again. If this bug
@@ -393,28 +426,74 @@ _filedir()
# because quotes-in-comments-in-a-subshell cause errors on
# bash-3.1. See also:
# http://www.mail-archive.com/bug-bash@gnu.org/msg01667.html
+ _quote_readline_by_ref "$cur" quoted
toks=( ${toks[@]-} $(
- compgen -d -- "$(quote_readline "$cur")" | {
+ compgen -d -- "$quoted" | {
while read -r tmp; do
printf '%s\n' $tmp
done
}
))
+ # On bash-3, special characters need to be escaped extra. This is
+ # unless the first character is a single quote ('). If the single
+ # quote appears further down the string, bash default completion also
+ # fails, e.g.:
+ #
+ # $ ls 'a&b/'
+ # f
+ # $ foo 'a&b/<TAB> # Becomes: foo 'a&b/f'
+ # $ foo a'&b/<TAB> # Nothing happens
+ #
if [[ "$1" != -d ]]; then
xspec=${1:+"!*.$1"}
- toks=( ${toks[@]-} $(
- compgen -f -X "$xspec" -- "$(quote_readline "$cur")" | {
- while read -r tmp; do
- [ -n $tmp ] && printf '%s\n' $tmp
+ if [[ ${cur:0:1} == "'" && ${BASH_VERSINFO[0]} -ge 4 ]]; then
+ toks=( ${toks[@]-} $(
+ eval compgen -f -X \"\$xspec\" -- $quoted
+ ) )
+ else
+ toks=( ${toks[@]-} $(
+ compgen -f -X "$xspec" -- $quoted
+ ) )
+ fi
+ if [ ${#toks[@]} -ne 0 ]; then
+ # If `compopt' is available, set `-o filenames'
+ compopt &>/dev/null && compopt -o filenames ||
+ # No, `compopt' isn't available;
+ # Is `-o filenames' set?
+ [[ "$(complete -p ${COMP_WORDS[0]})" == *"-o filenames"* ]] || {
+ # No, `-o filenames' isn't set;
+ # Emulate `-o filenames'
+ # NOTE: A side-effect of emulating `-o filenames' is that backslash escape
+ # characters are visible within the list of presented completions, e.g.
+ # the completions look like:
+ #
+ # $ foo a<TAB>
+ # a\ b/ a\$b/
+ #
+ # whereas with `-o filenames' active the completions look like:
+ #
+ # $ ls a<TAB>
+ # a b/ a$b/
+ #
+ for ((i=0; i < ${#toks[@]}; i++)); do
+ # If directory exists, append slash (/)
+ if [[ ${cur:0:1} != "'" ]]; then
+ [[ -d ${toks[i]} ]] && toks[i]="${toks[i]}"/
+ if [[ ${cur:0:1} == '"' ]]; then
+ toks[i]=${toks[i]//\\/\\\\}
+ toks[i]=${toks[i]//\"/\\\"}
+ toks[i]=${toks[i]//\$/\\\$}
+ else
+ toks[i]=$(printf %q ${toks[i]})
+ fi
+ fi
done
}
- ))
+ fi
fi
COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" )
- [ ${#COMPREPLY[@]} -ne 0 ] && type compopt &>/dev/null && \
- compopt -o filenames
} # _filedir()
diff --git a/test/fixture1/bar b/test/fixtures/_filedir/a b/i
similarity index 100%
copy from test/fixture1/bar
copy to test/fixtures/_filedir/a b/i
diff --git a/test/fixture1/bar "b/test/fixtures/_filedir/a\"b/d"
similarity index 100%
copy from test/fixture1/bar
copy to "test/fixtures/_filedir/a\"b/d"
diff --git a/test/fixture1/bar b/test/fixtures/_filedir/a$b/h
similarity index 100%
copy from test/fixture1/bar
copy to test/fixtures/_filedir/a$b/h
diff --git a/test/fixture1/bar b/test/fixtures/_filedir/a&b/f
similarity index 100%
copy from test/fixture1/bar
copy to test/fixtures/_filedir/a&b/f
diff --git a/test/fixture1/bar b/test/fixtures/_filedir/a'b/c
similarity index 100%
copy from test/fixture1/bar
copy to test/fixtures/_filedir/a'b/c
diff --git a/test/fixture1/bar "b/test/fixtures/_filedir/a\\b/g"
similarity index 100%
copy from test/fixture1/bar
copy to "test/fixtures/_filedir/a\\b/g"
diff --git a/test/fixture1/bar b/test/fixtures/_filedir/ab/e
similarity index 100%
copy from test/fixture1/bar
copy to test/fixtures/_filedir/ab/e
diff --git a/test/fixture1/bar b/test/fixtures/compgen/a'b/c
similarity index 100%
copy from test/fixture1/bar
copy to test/fixtures/compgen/a'b/c
diff --git a/test/fixtures/compgen/t1.txt b/test/fixtures/compgen/t1.txt
new file mode 100644
index 0000000..322a14d
--- /dev/null
+++ b/test/fixtures/compgen/t1.txt
@@ -0,0 +1,121 @@
+BASH=/bin/bash
+BASH_ARGC=()
+BASH_ARGV=()
+BASH_LINENO=()
+BASH_SOURCE=()
+BASH_VERSINFO=([0]="3" [1]="2" [2]="39" [3]="1" [4]="release" [5]="i486-pc-linux-gnu")
+BASH_VERSION='3.2.39(1)-release'
+CDPL_DIRS=([0]="/home/freddy/proj")
+CDPM_DIRS=
+CDP_DIRS=([0]="/home/freddy/proj" [1]="")
+COLUMNS=130
+COMP_CACHE=/home/freddy/.bash_completion_lib.d/cache~
+COMP_DIR=/etc/bash_completion_lib
+COMP_PATH=/home/freddy/.bash_completion_lib.d:/etc/bash_completion_lib
+COMP_RESTRICT_BY_EXTENSION=0
+COMP_VERSION=bash_completion_lib-1.3.1
+DIRSTACK=()
+EDITOR=/usr/bin/vim
+EUID=1000
+GPGKEY=10A575C3
+GPG_AGENT_INFO=/tmp/gpg-Pg6JXR/S.gpg-agent:4129:1
+GPG_TTY=/dev/pts/0
+GREP_OPTIONS='--exclude '\''distrib/*'\'' --exclude tags'
+GROUPS=()
+HISTCONTROL=ignoreboth
+HISTFILE=/home/freddy/.bash_history
+HISTFILESIZE=500
+HISTIGNORE=exit
+HISTSIZE=500
+HOME=/home/freddy
+HOSTNAME=blondy
+HOSTTYPE=i486
+IFS=$' \t\n'
+LANG=en_US
+LANGUAGE=en_NL:en_US:en_GB:en
+LINES=49
+LOGNAME=freddy
+MACHTYPE=i486-pc-linux-gnu
+MAIL=/var/mail/freddy
+MAILCHECK=60
+OLDPWD=/home/freddy/.bash_completion_lib.d
+OPTERR=1
+OPTIND=1
+OSTYPE=linux-gnu
+PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/home/freddy/proj/rc/bin
+PIPESTATUS=([0]="0")
+PPID=29352
+PS1=$'\\[\E[0;34m\\]\\!\\[\E[0m\\]\\[\E[1;32m\\]$(stoppedjobs)\\[\E[0m\\]:\\u@\\h:\\w> \\[\E[m\\]'
+PS2='> '
+PS4='+ '
+PWD=/home/freddy/proj/bashCompletion/bash-completion.git/test/fixtures/compgen
+SHELL=/bin/bash
+SHELLOPTS=braceexpand:hashall:histexpand:interactive-comments:monitor:vi
+SHLVL=1
+SSH_AUTH_SOCK=/tmp/ssh-xhQbo29352/agent.29352
+SSH_CLIENT='192.168.123.143 37670 4822'
+SSH_CONNECTION='192.168.123.143 37670 192.168.123.8 4822'
+SSH_TTY=/dev/pts/0
+TERM=xterm
+UID=1000
+USER=freddy
+VIM=/home/freddy/.vim
+VIMRUNTIME=/usr/share/vim/vimcurrent
+_=GPG_AGENT_INFO
+bash205='3.2.39(1)-release'
+bash205b='3.2.39(1)-release'
+bash3='3.2.39(1)-release'
+cdots ()
+{
+ [ -d "$1$2" ] && cd "$1$2" || eval cd "$1$2"
+}
+comp_load ()
+{
+ local cmd=${COMP_WORDS[0]} dir globs OLDIFS=$IFS;
+ IFS=:;
+ local -a aPaths=($COMP_PATH);
+ IFS='
+';
+ globs=($(
+ for dir in "${aPaths[@]}"; do
+ echo \"$dir\"/complete\*/\*.$cmd
+ echo \"$dir\"/complete\*/$cmd\!
+ echo \"$dir\"/complete\*/$cmd
+ done
+ ));
+ IFS=$OLDIFS;
+ if ! declare -F comp_include >&/dev/null; then
+ for dir in "${aPaths[@]}";
+ do
+ [ -r "$dir/include/comp_include" ] && . "$dir/include/comp_include" && break;
+ done;
+ fi;
+ comp_include comp_load_init;
+ comp_load_init;
+ local script="$(eval find "${globs[@]}" 2> /dev/null | head -1)";
+ local link comp=${script##*/};
+ [[ ${comp: -1:1} == ! ]] || {
+ link=${comp#*.};
+ comp=${comp%.$link}
+ };
+ local path=${script%/*};
+ [ "$script" -a -r "$path/$comp" ] && . "$path/$comp" && declare -F _$comp >&/dev/null && {
+ [ ${COMP_INSTALL:-1} -eq 0 ] || _comp_install $comp "$path"
+ } && _$comp $link;
+ comp_load_deinit
+}
+nameTerminal ()
+{
+ [ "${TERM:0:5}" = "xterm" ] && local ansiNrTab=0;
+ [ "$TERM" = "rxvt" ] && local ansiNrTab=61;
+ [ "$TERM" = "konsole" ] && local ansiNrTab=30 ansiNrWindow=0;
+ [ $ansiNrTab ] && echo -n ''"]$ansiNrTab;$1"'';
+ [ $ansiNrWindow -a "$2" ] && echo -n ''"]$ansiNrWindow;$2"''
+}
+stoppedjobs ()
+{
+ if [ "$(jobs -s)" ]; then
+ echo -n "%";
+ jobs -s | wc -l;
+ fi
+}
diff --git a/test/fixtures/compgen/t2.txt b/test/fixtures/compgen/t2.txt
new file mode 100644
index 0000000..371ab2b
--- /dev/null
+++ b/test/fixtures/compgen/t2.txt
@@ -0,0 +1,121 @@
+BASH=/bin/bash
+BASH_ARGC=()
+BASH_ARGV=()
+BASH_LINENO=()
+BASH_SOURCE=()
+BASH_VERSINFO=([0]="3" [1]="2" [2]="39" [3]="1" [4]="release" [5]="i486-pc-linux-gnu")
+BASH_VERSION='3.2.39(1)-release'
+CDPL_DIRS=([0]="/home/freddy/proj")
+CDPM_DIRS=
+CDP_DIRS=([0]="/home/freddy/proj" [1]="")
+COLUMNS=130
+COMP_CACHE=/home/freddy/.bash_completion_lib.d/cache~
+COMP_DIR=/etc/bash_completion_lib
+COMP_PATH=/home/freddy/.bash_completion_lib.d:/etc/bash_completion_lib
+COMP_RESTRICT_BY_EXTENSION=0
+COMP_VERSION=bash_completion_lib-1.3.1
+DIRSTACK=()
+EDITOR=/usr/bin/vim
+EUID=1000
+GPGKEY=10A575C3
+GPG_AGENT_INFO=/tmp/gpg-Pg6JXR/S.gpg-agent:4129:1
+GPG_TTY=/dev/pts/0
+GREP_OPTIONS='--exclude '\''distrib/*'\'' --exclude tags'
+GROUPS=()
+HISTCONTROL=ignoreboth
+HISTFILE=/home/freddy/.bash_history
+HISTFILESIZE=500
+HISTIGNORE=exit
+HISTSIZE=500
+HOME=/home/freddy
+HOSTNAME=blondy
+HOSTTYPE=i486
+IFS=$' \t\n'
+LANG=en_US
+LANGUAGE=en_NL:en_US:en_GB:en
+LINES=49
+LOGNAME=freddy
+MACHTYPE=i486-pc-linux-gnu
+MAIL=/var/mail/freddy
+MAILCHECK=60
+OLDPWD=/home/freddy/.bash_completion_lib.d
+OPTERR=1
+OPTIND=1
+OSTYPE=linux-gnu
+PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/home/freddy/proj/rc/bin
+PIPESTATUS=([0]="0")
+PPID=29352
+PS1=$'\\[\E[0;34m\\]\\!\\[\E[0m\\]\\[\E[1;32m\\]$(stoppedjobs)\\[\E[0m\\]:\\u@\\h:\\w> \\[\E[m\\]'
+PS2='> '
+PS4='+ '
+PWD=/home/freddy/proj/bashCompletion/bash-completion.git/test/fixtures/compgen
+SHELL=/bin/bash
+SHELLOPTS=braceexpand:hashall:histexpand:interactive-comments:monitor:vi
+SHLVL=1
+SSH_AUTH_SOCK=/tmp/ssh-xhQbo29352/agent.29352
+SSH_CLIENT='192.168.123.143 37670 4822'
+SSH_CONNECTION='192.168.123.143 37670 192.168.123.8 4822'
+SSH_TTY=/dev/pts/0
+TERM=xterm
+UID=1000
+USER=freddy
+VIM=/home/freddy/.vim
+VIMRUNTIME=/usr/share/vim/vimcurrent
+_='a\\\'\''b/'
+bash205='3.2.39(1)-release'
+bash205b='3.2.39(1)-release'
+bash3='3.2.39(1)-release'
+cdots ()
+{
+ [ -d "$1$2" ] && cd "$1$2" || eval cd "$1$2"
+}
+comp_load ()
+{
+ local cmd=${COMP_WORDS[0]} dir globs OLDIFS=$IFS;
+ IFS=:;
+ local -a aPaths=($COMP_PATH);
+ IFS='
+';
+ globs=($(
+ for dir in "${aPaths[@]}"; do
+ echo \"$dir\"/complete\*/\*.$cmd
+ echo \"$dir\"/complete\*/$cmd\!
+ echo \"$dir\"/complete\*/$cmd
+ done
+ ));
+ IFS=$OLDIFS;
+ if ! declare -F comp_include >&/dev/null; then
+ for dir in "${aPaths[@]}";
+ do
+ [ -r "$dir/include/comp_include" ] && . "$dir/include/comp_include" && break;
+ done;
+ fi;
+ comp_include comp_load_init;
+ comp_load_init;
+ local script="$(eval find "${globs[@]}" 2> /dev/null | head -1)";
+ local link comp=${script##*/};
+ [[ ${comp: -1:1} == ! ]] || {
+ link=${comp#*.};
+ comp=${comp%.$link}
+ };
+ local path=${script%/*};
+ [ "$script" -a -r "$path/$comp" ] && . "$path/$comp" && declare -F _$comp >&/dev/null && {
+ [ ${COMP_INSTALL:-1} -eq 0 ] || _comp_install $comp "$path"
+ } && _$comp $link;
+ comp_load_deinit
+}
+nameTerminal ()
+{
+ [ "${TERM:0:5}" = "xterm" ] && local ansiNrTab=0;
+ [ "$TERM" = "rxvt" ] && local ansiNrTab=61;
+ [ "$TERM" = "konsole" ] && local ansiNrTab=30 ansiNrWindow=0;
+ [ $ansiNrTab ] && echo -n ''"]$ansiNrTab;$1"'';
+ [ $ansiNrWindow -a "$2" ] && echo -n ''"]$ansiNrWindow;$2"''
+}
+stoppedjobs ()
+{
+ if [ "$(jobs -s)" ]; then
+ echo -n "%";
+ jobs -s | wc -l;
+ fi
+}
diff --git a/test/fixtures/compgen/t3.txt b/test/fixtures/compgen/t3.txt
new file mode 100644
index 0000000..371ab2b
--- /dev/null
+++ b/test/fixtures/compgen/t3.txt
@@ -0,0 +1,121 @@
+BASH=/bin/bash
+BASH_ARGC=()
+BASH_ARGV=()
+BASH_LINENO=()
+BASH_SOURCE=()
+BASH_VERSINFO=([0]="3" [1]="2" [2]="39" [3]="1" [4]="release" [5]="i486-pc-linux-gnu")
+BASH_VERSION='3.2.39(1)-release'
+CDPL_DIRS=([0]="/home/freddy/proj")
+CDPM_DIRS=
+CDP_DIRS=([0]="/home/freddy/proj" [1]="")
+COLUMNS=130
+COMP_CACHE=/home/freddy/.bash_completion_lib.d/cache~
+COMP_DIR=/etc/bash_completion_lib
+COMP_PATH=/home/freddy/.bash_completion_lib.d:/etc/bash_completion_lib
+COMP_RESTRICT_BY_EXTENSION=0
+COMP_VERSION=bash_completion_lib-1.3.1
+DIRSTACK=()
+EDITOR=/usr/bin/vim
+EUID=1000
+GPGKEY=10A575C3
+GPG_AGENT_INFO=/tmp/gpg-Pg6JXR/S.gpg-agent:4129:1
+GPG_TTY=/dev/pts/0
+GREP_OPTIONS='--exclude '\''distrib/*'\'' --exclude tags'
+GROUPS=()
+HISTCONTROL=ignoreboth
+HISTFILE=/home/freddy/.bash_history
+HISTFILESIZE=500
+HISTIGNORE=exit
+HISTSIZE=500
+HOME=/home/freddy
+HOSTNAME=blondy
+HOSTTYPE=i486
+IFS=$' \t\n'
+LANG=en_US
+LANGUAGE=en_NL:en_US:en_GB:en
+LINES=49
+LOGNAME=freddy
+MACHTYPE=i486-pc-linux-gnu
+MAIL=/var/mail/freddy
+MAILCHECK=60
+OLDPWD=/home/freddy/.bash_completion_lib.d
+OPTERR=1
+OPTIND=1
+OSTYPE=linux-gnu
+PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/home/freddy/proj/rc/bin
+PIPESTATUS=([0]="0")
+PPID=29352
+PS1=$'\\[\E[0;34m\\]\\!\\[\E[0m\\]\\[\E[1;32m\\]$(stoppedjobs)\\[\E[0m\\]:\\u@\\h:\\w> \\[\E[m\\]'
+PS2='> '
+PS4='+ '
+PWD=/home/freddy/proj/bashCompletion/bash-completion.git/test/fixtures/compgen
+SHELL=/bin/bash
+SHELLOPTS=braceexpand:hashall:histexpand:interactive-comments:monitor:vi
+SHLVL=1
+SSH_AUTH_SOCK=/tmp/ssh-xhQbo29352/agent.29352
+SSH_CLIENT='192.168.123.143 37670 4822'
+SSH_CONNECTION='192.168.123.143 37670 192.168.123.8 4822'
+SSH_TTY=/dev/pts/0
+TERM=xterm
+UID=1000
+USER=freddy
+VIM=/home/freddy/.vim
+VIMRUNTIME=/usr/share/vim/vimcurrent
+_='a\\\'\''b/'
+bash205='3.2.39(1)-release'
+bash205b='3.2.39(1)-release'
+bash3='3.2.39(1)-release'
+cdots ()
+{
+ [ -d "$1$2" ] && cd "$1$2" || eval cd "$1$2"
+}
+comp_load ()
+{
+ local cmd=${COMP_WORDS[0]} dir globs OLDIFS=$IFS;
+ IFS=:;
+ local -a aPaths=($COMP_PATH);
+ IFS='
+';
+ globs=($(
+ for dir in "${aPaths[@]}"; do
+ echo \"$dir\"/complete\*/\*.$cmd
+ echo \"$dir\"/complete\*/$cmd\!
+ echo \"$dir\"/complete\*/$cmd
+ done
+ ));
+ IFS=$OLDIFS;
+ if ! declare -F comp_include >&/dev/null; then
+ for dir in "${aPaths[@]}";
+ do
+ [ -r "$dir/include/comp_include" ] && . "$dir/include/comp_include" && break;
+ done;
+ fi;
+ comp_include comp_load_init;
+ comp_load_init;
+ local script="$(eval find "${globs[@]}" 2> /dev/null | head -1)";
+ local link comp=${script##*/};
+ [[ ${comp: -1:1} == ! ]] || {
+ link=${comp#*.};
+ comp=${comp%.$link}
+ };
+ local path=${script%/*};
+ [ "$script" -a -r "$path/$comp" ] && . "$path/$comp" && declare -F _$comp >&/dev/null && {
+ [ ${COMP_INSTALL:-1} -eq 0 ] || _comp_install $comp "$path"
+ } && _$comp $link;
+ comp_load_deinit
+}
+nameTerminal ()
+{
+ [ "${TERM:0:5}" = "xterm" ] && local ansiNrTab=0;
+ [ "$TERM" = "rxvt" ] && local ansiNrTab=61;
+ [ "$TERM" = "konsole" ] && local ansiNrTab=30 ansiNrWindow=0;
+ [ $ansiNrTab ] && echo -n ''"]$ansiNrTab;$1"'';
+ [ $ansiNrWindow -a "$2" ] && echo -n ''"]$ansiNrWindow;$2"''
+}
+stoppedjobs ()
+{
+ if [ "$(jobs -s)" ]; then
+ echo -n "%";
+ jobs -s | wc -l;
+ fi
+}
diff --git a/test/lib/completions/screen.exp b/test/lib/completions/screen.exp
index a9d239e..4bd5ad0 100644
--- a/test/lib/completions/screen.exp
+++ b/test/lib/completions/screen.exp
@@ -33,6 +33,11 @@ expect {
-re "\r\nbar\\s+bar bar.d\\s+foo\\s+foo.d" {
if {[lindex $BASH_VERSINFO 0] < 4} {xfail "$test"} {fail "$test"}
}
+ -re "\r\nbar\\s+bar\\\\ bar.d/\\s+foo\\s+foo.d/" {
+ # On bash-3, the space in `bar bar.d' is escaped with a backslash
+ # as a side-effect of emulating `-o filenames'.
+ if {[lindex $BASH_VERSINFO 0] <= 3} {pass "$test"} {fail "$test"}
+ }
-re $prompt { unresolved "$test at prompt" }
default { unresolved "$test" }
}; # expect
diff --git a/test/unit/_filedir.exp b/test/unit/_filedir.exp
new file mode 100644
index 0000000..c5dd877
--- /dev/null
+++ b/test/unit/_filedir.exp
@@ -0,0 +1,234 @@
+proc setup {} {
+ assert_bash_exec {unset COMPREPLY cur}
+ assert_bash_exec {unset -f _f}
+ save_env
+ # Declare bash completion function `_f'
+ assert_bash_exec { \
+ _f() { local cur=$(_get_cword); unset COMPREPLY; _filedir; }; \
+ complete -F _f f \
+ }
+ # Declare bash completion function `_f2' with `-o filenames' active.
+ assert_bash_exec { \
+ complete -F _f -o filenames f2 \
+ }
+ # Create directory `a*b'
+ # NOTE: directory `a*b' isn't included in Git, because a directory
+ # containing an asterisk (*) causes troubles on Cygwin/Windows
+ assert_bash_exec {(cd fixtures/_filedir && [ ! -d a\*b ] && mkdir a\*b && touch a\*b/j || true)}
+}; # setup()
+
+
+proc teardown {} {
+ assert_bash_exec {(cd fixtures/_filedir && rm -- a\*b/j && rmdir a\*b/ || true)}
+ assert_bash_exec {unset COMPREPLY cur}
+ assert_bash_exec {unset -f _f}
+ assert_bash_exec {complete -r f}
+ assert_env_unmodified { /OLDPWD/d }
+}; # teardown()
+
+
+setup
+
+
+set test "_filedir should run without errors"
+assert_bash_exec {_filedir > /dev/null} $test
+
+
+sync_after_int
+
+
+foreach name {f f2} {
+
+ set test "completing $name ab/ should return e"
+ set cmd "$name ab/"
+ assert_complete_dir e $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name a\\ b/ should return i"
+ set cmd "$name a\\ b/"
+ assert_complete_dir i $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name a\\\'b/ should return i"
+ set cmd "$name a\\\'b/"
+ assert_complete_dir c $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name a\\\"b/ should return i"; #"
+ set cmd "$name a\\\"b/"; #"
+ assert_complete_dir d $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name a\\\$b/ should return h"
+ set cmd "$name a\\\$b/"
+ assert_complete_dir "\b\b\b\b\b$::TESTDIR/fixtures/_filedir/a\\\\\$b/h" $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name a\\\\b/ should return g"
+ set cmd "$name a\\\\b/"
+ assert_complete_dir g $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name a\\&b/ should return f"
+ set cmd "$name a\\&b/"
+ assert_complete_dir f $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name a\$ should return a\\\$b/"
+ set cmd "$name a\$"
+ assert_complete_dir "\b\\\\\$b/" $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ # NOTE: Bash versions 4.0.0 up to 4.0.34 contain a bug when completing quoted
+ # words, so tests within this if aren't executed for these bash versions.
+ if {! (
+ [lindex $::BASH_VERSINFO 0] == 4 &&
+ [lindex $::BASH_VERSINFO 1] == 0 &&
+ [lindex $::BASH_VERSINFO 2] < 35
+ )} {
+ set test "completing $name 'ab/ should return e"
+ set cmd "$name 'ab/"
+ assert_complete_dir {e'} $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name 'a b/ should return i"
+ set cmd "$name 'a b/"
+ assert_complete_dir {i'} $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name 'a\"b/ should return d"; #"
+ set cmd "$name 'a\"b/"; #"
+ assert_complete_dir {d'} $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name 'a\$b/ should return h"
+ set cmd "$name 'a\$b/"
+ if {[lindex $::BASH_VERSINFO 0] == 4} {
+ assert_complete_dir {h'} $cmd "fixtures/_filedir"
+ } else {
+ assert_complete_dir "\b\b\b\b$::TESTDIR/fixtures/_filedir/a\$b/h'" $cmd "fixtures/_filedir"
+ }; # if
+
+
+
+ sync_after_int
+
+
+ set test "completing $name 'a\\b/ should return g"
+ set cmd "$name 'a\\b/"
+ assert_complete_dir {g'} $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name 'a&b/ should return f"
+ set cmd "$name 'a&b/"
+ assert_complete_dir {f'} $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name \"ab/ should return e"; #"
+ set cmd "$name \"ab/"; #"
+ assert_complete_dir {e"} $cmd "fixtures/_filedir"; #"
+
+
+ sync_after_int
+
+
+ set test "completing $name \"a b/ should return i"; #"
+ set cmd "$name \"a b/"; #"
+ assert_complete_dir {i"} $cmd "fixtures/_filedir"; #"
+
+
+ sync_after_int
+
+
+ set test "completing $name \"a'b/ should return c"; #"
+ set cmd "$name \"a'b/"; #"
+ assert_complete_dir {c"} $cmd "fixtures/_filedir"; #"
+
+
+ sync_after_int
+
+
+ set test "completing $name \"a\\\"b/ should return d"; #"
+ set cmd "$name \"a\\\"b/"; #"
+ assert_complete_dir {d"} $cmd "fixtures/_filedir"; #"
+
+
+ sync_after_int
+
+
+ set test "completing $name \"a\\\$b/ should return h"; #"
+ set cmd "$name \"a\\\$b/"; #"
+ assert_complete_dir "\b\b\b\b\b$::TESTDIR/fixtures/_filedir/a\\\\\$b/h\\\"" $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name \"a\\b/ should return e"; #"
+ set cmd "$name \"a\\b/"; #"
+ assert_complete_dir "\b\b\bb/e\\\"" $cmd "fixtures/_filedir"
+
+
+ sync_after_int
+
+
+ set test "completing $name \"a\\\\b/ should return g"; #"
+ set cmd "$name \"a\\\\b/"; #"
+ assert_complete_dir {g"} $cmd "fixtures/_filedir"; #"
+
+
+ sync_after_int
+
+
+ set test "completing $name \"a&b/ should return f"; #"
+ set cmd "$name \"a&b/"; #"
+ assert_complete_dir {f"} $cmd "fixtures/_filedir"; #"
+
+
+ sync_after_int
+
+
+ }; # if
+}; # for
+
+
+teardown
diff --git a/test/unit/_get_cword.exp b/test/unit/_get_cword.exp
index 3481b4a..7e38e9e 100644
--- a/test/unit/_get_cword.exp
+++ b/test/unit/_get_cword.exp
@@ -253,4 +253,32 @@ expect {
sync_after_int
+set test {a 'b&c| should return 'b&c}; # | = cursor position
+if {
+ [lindex $::BASH_VERSINFO 0] == 4 &&
+ [lindex $::BASH_VERSINFO 1] == 0 &&
+ [lindex $::BASH_VERSINFO 2] < 35
+} {
+ set cmd {COMP_WORDS=(a "'" b "&" c); COMP_CWORD=4}
+} else {
+ set cmd {COMP_WORDS=(a "'b&c"); COMP_CWORD=1}
+}; # if
+append cmd {; COMP_LINE="a 'b&c"; COMP_POINT=6; _get_cword}
+send "$cmd\r"
+expect -ex "$cmd\r\n"
+expect {
+ -ex "'b&c/@" { pass "$test" }
+ -ex "c/@" {
+ if {
+ [lindex $::BASH_VERSINFO 0] == 4 &&
+ [lindex $::BASH_VERSINFO 1] == 0 &&
+ [lindex $::BASH_VERSINFO 2] < 35
+ } {xfail "$test"} {fail "$test"}
+ }
+}; # expect
+
+
+sync_after_int
+
+
teardown
diff --git a/test/unit/compgen.exp b/test/unit/compgen.exp
new file mode 100644
index 0000000..8c33c41
--- /dev/null
+++ b/test/unit/compgen.exp
@@ -0,0 +1,52 @@
+proc setup {} {
+ save_env
+}; # setup()
+
+
+proc teardown {} {
+ assert_env_unmodified {/OLDPWD/d}
+}; # teardown()
+
+
+setup
+
+
+if {[lindex $::BASH_VERSINFO 0] <= 3} {
+ set test {compgen -f a\\\\\\\'b/ on bash-3 should return a\'b/c};
+ set cmd {compgen -f a\\\\\\\'b/}
+} else {
+ set test {compgen -f a\\\'b/ on bash-4 should return a\'b/c};
+ set cmd {compgen -f a\\\'b/}
+}; # if
+set dir fixtures/compgen
+set prompt "/$dir/@"
+assert_bash_exec "cd $dir" "" $prompt
+send "$cmd\r"
+expect -ex "$cmd\r\n"
+expect {
+ -re {a\\\'b/c} {
+ # On bash-3.2, compgen returns inconsequent output
+ if {
+ [lindex $::BASH_VERSINFO 0] >= 4 || (
+ [lindex $::BASH_VERSINFO 0] == 3 &&
+ [lindex $::BASH_VERSINFO 1] == 2
+ )
+ } {pass $test} else {fail $test}
+ }
+ -re {a'b/c} {
+ if {[lindex $::BASH_VERSINFO 0] <= 3 } \
+ {pass $test} else {fail $test}
+ }
+ -re $prompt { pass "$test" }
+ -re eof { unresolved "eof" }
+}; # expect
+sync_after_int $prompt
+assert_bash_exec "cd \$TESTDIR"
+
+#assert_bash_list_dir {a\\\'b/c} $cmd fixtures/compgen
+
+
+sync_after_int
+
+
+teardown
--
bash-completion
More information about the Bash-completion-commits
mailing list