Merge branch 'master' of git+ssh://git.debian.org/git/bash-completion/bash-completion

This commit is contained in:
David Paleino 2010-03-08 12:38:33 +01:00
commit 8755f716fc
23 changed files with 375 additions and 127 deletions

21
CHANGES
View File

@ -25,9 +25,10 @@ bash-completion (2.x)
* Apply cardctl completion to pccardctl too. * Apply cardctl completion to pccardctl too.
* Apply pine completion to alpine too. * Apply pine completion to alpine too.
* Remove many unnecessary short option completions where long ones exist. * Remove many unnecessary short option completions where long ones exist.
* Improve chsh, configure, cvs, gkrellm, gzip, lftp, look, make, mdadm, * Improve chsh, chgrp, chown, configure, cvs, gkrellm, gzip, lftp, look,
modprobe, mplayer, mysqladmin, rsync, screen, service, scp, ssh, sshfs, make, mdadm, modprobe, mplayer, mysqladmin, perldoc, rsync, screen,
update-alternatives, vncviewer, yp-tools, and general hostname completions. service, scp, ssh, sshfs, update-alternatives, vncviewer, yp-tools, and
general hostname completions.
* Add abook and wtf completion, based on work by Raphaël Droz. * Add abook and wtf completion, based on work by Raphaël Droz.
* Add cvsps, dragon, fusermount, jarsigner, k3b, lftpget, pm-utils, rtcwake, * Add cvsps, dragon, fusermount, jarsigner, k3b, lftpget, pm-utils, rtcwake,
pack200, unpack200, pbzip2, pbunzip2, pbzcat, pigz and unpigz completions. pack200, unpack200, pbzip2, pbunzip2, pbzcat, pigz and unpigz completions.
@ -54,6 +55,7 @@ bash-completion (2.x)
* Split mount and umount completion into contrib/mount. * Split mount and umount completion into contrib/mount.
* Do basic HTML file completion with Firefox and Chrome and friends, * Do basic HTML file completion with Firefox and Chrome and friends,
and Epiphany. and Epiphany.
* Do basic diff/patch completion with cdiff and kompare.
[ Freddy Vulto ] [ Freddy Vulto ]
* Added _get_pword() helper function, thanks to Sung Pae (Alioth: #312030) * Added _get_pword() helper function, thanks to Sung Pae (Alioth: #312030)
@ -69,6 +71,12 @@ bash-completion (2.x)
* Fix NFS mounts completion (Alioth: #312285). * Fix NFS mounts completion (Alioth: #312285).
* Fix completion of usernames (Alioth: #311396, Debian: #511788). * Fix completion of usernames (Alioth: #311396, Debian: #511788).
* Fix chown test crashing on systems with no root group (Alioth: #312306). * Fix chown test crashing on systems with no root group (Alioth: #312306).
* Fixed tests when BASH_COMPLETION or TESTDIR contain spaces.
* Fix mount handling of escapes (Alioth: #311410, Launchpad: #219971).
* Cleanup scripts to run tests. Make runUnit and runCompletion use test/run.
Make it possible to run tests from any directory.
* Add a --debug-xtrace option to test/run using BASH_XTRACEFD from bash-4.1.
* Add a --timeout option to test/run to override the default expect timeout.
[ Raphaël Droz ] [ Raphaël Droz ]
* Add xsltproc completion (Alioth: #311843). * Add xsltproc completion (Alioth: #311843).
@ -79,6 +87,9 @@ bash-completion (2.x)
[ Ildar Mulyukov ] [ Ildar Mulyukov ]
* Add showmount completion (Alioth: #312285). * Add showmount completion (Alioth: #312285).
[ Neville Gao ]
* Fix mount completion error "bash: [: too many arguments" (Alioth #312381).
-- David Paleino <d.paleino@gmail.com> Sun, 11 Oct 2009 11:11:57 +0200 -- David Paleino <d.paleino@gmail.com> Sun, 11 Oct 2009 11:11:57 +0200
bash-completion (1.1) bash-completion (1.1)
@ -265,6 +276,10 @@ bash-completion (1.1)
* Fix leaking $muttcmd from mutt completion * Fix leaking $muttcmd from mutt completion
* Fix completing multiple hosts (Debian: #535585) * Fix completing multiple hosts (Debian: #535585)
[ Michele Ballabio ]
* Add more extensions to pkgtools completion.
-- David Paleino <d.paleino@gmail.com> Sat, 03 Oct 2009 15:41:49 +0200 -- David Paleino <d.paleino@gmail.com> Sat, 03 Oct 2009 15:41:49 +0200
bash-completion (1.0) bash-completion (1.0)

36
README
View File

@ -12,7 +12,7 @@ if [ -f /etc/bash_completion ]; then
. /etc/bash_completion . /etc/bash_completion
fi fi
(if you happen to have *only* bash >= 3, see further if not) (if you happen to have *only* bash >= 3.2 installed, see further if not)
If you don't have the package readily available for your distribution, or If you don't have the package readily available for your distribution, or
you simply don't want to do this, put the bash_completion file somewhere you simply don't want to do this, put the bash_completion file somewhere
@ -98,36 +98,6 @@ function used by mutt completion, where the function calls itself
recursively. This seems to confuse bash and it issues spurious recursively. This seems to confuse bash and it issues spurious
warnings if 'nounset' is set. warnings if 'nounset' is set.
V.
After upgrading to bash 3.1, you may notice that completing on certain
commands now fails with a message something like this:
sed: -e expression #1, char 20: unterminated `s' command
The reason for this is that bash 3.1 contains the following,
innocent-looking bug fix (from bash's CHANGES file):
t. Fixed a bug that caused the expanded value of a $'...' string
to be incorrectly re-quoted if it occurred within a
double-quoted ${...} parameter expansion.
Unfortunately, this also had the side effect of causing single quotes
to be stripped from $'...' strings inside double-quoted command
substitutions. Confused?
Efforts have been made to work around this issue in the bash
completion code as of the 20060301 release. All previous versions are
vulnerable to the problem. However, it's possible that, even in the
20060301 release and later, affected code remains.
The issue has now been officially recognised as a regression in the
bash 3.1 release and is fixed by official patch 11. If you encounter
problems of this nature, please apply the patch below to your copy of
bash:
ftp://ftp.gnu.org/gnu/bash/bash-3.1-patches/bash31-011
FAQ FAQ
--- ---
@ -318,10 +288,10 @@ guidelines in mind:
start interpreters. Use lightweight programs such as grep(1), awk(1) start interpreters. Use lightweight programs such as grep(1), awk(1)
and sed(1). and sed(1).
- Use the full power of bash >= 3. We no longer support earlier bash - Use the full power of bash >= 3.2. We no longer support earlier bash
versions, so you may as well use all the features of that version of versions, so you may as well use all the features of that version of
bash to optimise your code. However, be careful when using features bash to optimise your code. However, be careful when using features
added since bash 3.0, since not everyone will be able to use them. Be added since bash 3.2, since not everyone will be able to use them. Be
ESPECIALLY careful of using features exclusive to 4.x, as many people ESPECIALLY careful of using features exclusive to 4.x, as many people
are still using 3.x. are still using 3.x.

4
TODO
View File

@ -2,8 +2,8 @@ bash completion needs to be rewritten from the ground up.
--------------------------------------------------------- ---------------------------------------------------------
bash completion really needs to be rewritten from the ground up, using all of bash completion really needs to be rewritten from the ground up, using all of
the features available in bash 3.1 and without regard for compatibility with the features available in bash 3.2+ and without regard for compatibility with
the 2.x line. earlier versions.
At that time, it should be split into multiple files for easier source At that time, it should be split into multiple files for easier source
management. Whether or not it is actually installed on the destination management. Whether or not it is actually installed on the destination

View File

@ -1,5 +1,5 @@
# #
# bash_completion - programmable completion functions for bash 3.x # bash_completion - programmable completion functions for bash 3.2+
# #
# Copyright © 2006-2008, Ian Macdonald <ian@caliban.org> # Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
# © 2009-2010, Bash Completion Maintainers # © 2009-2010, Bash Completion Maintainers
@ -121,6 +121,7 @@ complete -f -X '!*.po' poedit gtranslator kbabel lokalize
complete -f -X '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp complete -f -X '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp
complete -f -X '!*.[Hh][Rr][Bb]' hbrun complete -f -X '!*.[Hh][Rr][Bb]' hbrun
complete -f -X '!*.ly' lilypond ly2dvi complete -f -X '!*.ly' lilypond ly2dvi
complete -f -X '!*.@(dif?(f)|?(d)patch)' cdiff kompare
# FINISH exclude -- do not remove this line # FINISH exclude -- do not remove this line
# start of section containing compspecs that can be handled within bash # start of section containing compspecs that can be handled within bash
@ -1084,9 +1085,13 @@ _chown()
if [[ "$cur" == -* ]]; then if [[ "$cur" == -* ]]; then
# Complete -options # Complete -options
local w opts
for w in "${COMP_WORDS[@]}" ; do
[[ "$w" == -@(R|-recursive) ]] && opts="-H -L -P" && break
done
COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes --dereference \ COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes --dereference \
--no-dereference --from --silent --quiet --reference --recursive \ --no-dereference --from --silent --quiet --reference --recursive \
--verbose --help --version' -- "$cur" ) ) --verbose --help --version $opts' -- "$cur" ) )
else else
local args local args
@ -1125,9 +1130,13 @@ _chgrp()
# options completion # options completion
if [[ "$cur" == -* ]]; then if [[ "$cur" == -* ]]; then
local w opts
for w in "${COMP_WORDS[@]}" ; do
[[ "$w" == -@(R|-recursive) ]] && opts="-H -L -P" && break
done
COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes --dereference \ COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes --dereference \
--no-dereference --silent --quiet --reference --recursive \ --no-dereference --silent --quiet --reference --recursive \
--verbose --help --version' -- "$cur" ) ) --verbose --help --version $opts' -- "$cur" ) )
return 0 return 0
fi fi
@ -1810,7 +1819,7 @@ _filedir_xspec()
# get first exclusion compspec that matches this command # get first exclusion compspec that matches this command
xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \$0; exit }" \ xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \$0; exit }" \
$BASH_COMPLETION ) "$BASH_COMPLETION" )
# prune to leave nothing but the -X spec # prune to leave nothing but the -X spec
xspec=${xspec#*-X } xspec=${xspec#*-X }
xspec=${xspec%% *} xspec=${xspec%% *}
@ -1837,7 +1846,7 @@ _filedir_xspec()
COMPREPLY=( "${toks[@]}" ) COMPREPLY=( "${toks[@]}" )
} }
list=( $( sed -ne '/^# START exclude/,/^# FINISH exclude/p' $BASH_COMPLETION | \ list=( $( sed -ne '/^# START exclude/,/^# FINISH exclude/p' "$BASH_COMPLETION" | \
# read exclusion compspecs # read exclusion compspecs
( (
while read line while read line
@ -1863,19 +1872,19 @@ unset list
# source completion directory definitions # source completion directory definitions
if [[ -d $BASH_COMPLETION_COMPAT_DIR && -r $BASH_COMPLETION_COMPAT_DIR && \ if [[ -d $BASH_COMPLETION_COMPAT_DIR && -r $BASH_COMPLETION_COMPAT_DIR && \
-x $BASH_COMPLETION_COMPAT_DIR ]]; then -x $BASH_COMPLETION_COMPAT_DIR ]]; then
for i in $(LC_ALL=C command ls $BASH_COMPLETION_COMPAT_DIR); do for i in $(LC_ALL=C command ls "$BASH_COMPLETION_COMPAT_DIR"); do
i=$BASH_COMPLETION_COMPAT_DIR/$i i=$BASH_COMPLETION_COMPAT_DIR/$i
[[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) \ [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) \
&& ( -f $i || -h $i ) && -r $i ]] && . $i && ( -f $i || -h $i ) && -r $i ]] && . "$i"
done done
fi fi
if [[ $BASH_COMPLETION_DIR != $BASH_COMPLETION_COMPAT_DIR && \ if [[ $BASH_COMPLETION_DIR != $BASH_COMPLETION_COMPAT_DIR && \
-d $BASH_COMPLETION_DIR && -r $BASH_COMPLETION_DIR && \ -d $BASH_COMPLETION_DIR && -r $BASH_COMPLETION_DIR && \
-x $BASH_COMPLETION_DIR ]]; then -x $BASH_COMPLETION_DIR ]]; then
for i in $(LC_ALL=C command ls $BASH_COMPLETION_DIR); do for i in $(LC_ALL=C command ls "$BASH_COMPLETION_DIR"); do
i=$BASH_COMPLETION_DIR/$i i=$BASH_COMPLETION_DIR/$i
[[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) \ [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) \
&& ( -f $i || -h $i ) && -r $i ]] && . $i && ( -f $i || -h $i ) && -r $i ]] && . "$i"
done done
fi fi
unset i unset i

View File

@ -2,9 +2,11 @@
[ -z "$BASH_VERSION" -o -z "$PS1" -o -n "$BASH_COMPLETION" ] && return [ -z "$BASH_VERSION" -o -z "$PS1" -o -n "$BASH_COMPLETION" ] && return
# Check for recent enough version of bash. # Check for recent enough version of bash.
bash=${BASH_VERSION%.*}; bmajor=${bash%.*} bash=${BASH_VERSION%.*}; bmajor=${bash%.*}; bminor=${bash#*.}
if [ $bmajor -ge 3 -a -r @sysconfdir@/bash_completion ]; then if [ $bmajor -gt 3 ] || [ $bmajor -eq 3 -a $bminor -ge 2 ]; then
# Source completion code. if [ -r @sysconfdir@/bash_completion ]; then
. @sysconfdir@/bash_completion # Source completion code.
. @sysconfdir@/bash_completion
fi
fi fi
unset bash bmajor unset bash bmajor bminor

View File

@ -7,6 +7,74 @@
have mount && have mount &&
{ {
# Just like COMPREPLY=(`compgen -W "${COMPREPLY[*]}" -- "$cur"`), only better!
#
# This will correctly escape special characters in COMPREPLY.
_reply_compgen_array()
{
# Create the argument for compgen -W by escaping twice.
#
# One round of escape is because we want to reply with escaped arguments. A
# second round is required because compgen -W will helpfully expand it's
# argument.
local i wlist
for i in ${!COMPREPLY[*]}; do
local q=$(quote "$(printf %q "${COMPREPLY[$i]}")")
wlist+=$q$'\n'
done
# We also have to add another round of escaping to $cur.
local ecur="$cur"
ecur="${ecur//\\/\\\\}"
ecur="${ecur//\'/\'}"
# Actually generate completions.
local oldifs=$IFS
IFS=$'\n' eval 'COMPREPLY=(`compgen -W "$wlist" -- "${ecur}"`)'
IFS=$oldifs
}
# Unescape strings in the linux fstab(5) format (with octal escapes).
__linux_fstab_unescape() {
eval $1="'${!1//\'/\047}'"
eval $1="'${!1/%\\/\\\\}'"
eval "$1=$'${!1}'"
}
# Complete linux fstab entries.
#
# Reads a file from stdin in the linux fstab(5) format; as used by /etc/fstab
# and /proc/mounts.
_linux_fstab()
{
COMPREPLY=()
# Read and unescape values into COMPREPLY
local fs_spec fs_file fs_other
local oldifs="$IFS"
while read -r fs_spec fs_file fs_other; do
if [[ $fs_spec = [#]* ]]; then continue; fi
if [[ $1 == -L ]]; then
local fs_label=${fs_spec/#LABEL=}
if [[ $fs_label != "$fs_spec" ]]; then
__linux_fstab_unescape fs_label
IFS=$'\0'
COMPREPLY+=("$fs_label")
IFS=$oldifs
fi
else
__linux_fstab_unescape fs_spec
__linux_fstab_unescape fs_file
IFS=$'\0'
[[ $fs_spec = */* ]] && COMPREPLY+=("$fs_spec")
[[ $fs_file = */* ]] && COMPREPLY+=("$fs_file")
IFS=$oldifs
fi
done
_reply_compgen_array
}
_mount() _mount()
{ {
local cur sm host prev local cur sm host prev
@ -17,7 +85,7 @@ _mount()
[[ "$cur" == \\ ]] && cur="/" [[ "$cur" == \\ ]] && cur="/"
if [[ "$cur" == *:* ]]; then if [[ "$cur" == *:* ]]; then
for sm in $(type -P showmount) {,/usr}/{,s}bin/showmount; do for sm in "$(type -P showmount)" {,/usr}/{,s}bin/showmount; do
[ -x "$sm" ] || continue [ -x "$sm" ] || continue
COMPREPLY=( $( compgen -W "$( "$sm" -e ${cur%%:*} | \ COMPREPLY=( $( compgen -W "$( "$sm" -e ${cur%%:*} | \
awk 'NR>1 {print $1}' )" -- "${cur#*:}" ) ) awk 'NR>1 {print $1}' )" -- "${cur#*:}" ) )
@ -43,12 +111,12 @@ _mount()
COMPREPLY=( $( compgen -W "$( mount | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' )" -- "$cur" ) ) COMPREPLY=( $( compgen -W "$( mount | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' )" -- "$cur" ) )
else else
# probably Linux # probably Linux
if [ $prev = -L ]; then if [ "$prev" = -L ]; then
COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*LABEL=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- "$cur" ) ) _linux_fstab -L < /etc/fstab
elif [ $prev = -U ]; then elif [ "$prev" = -U ]; then
COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*UUID=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- "$cur" ) ) COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*UUID=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- "$cur" ) )
else else
COMPREPLY=( $( compgen -W "$( awk '! /^[ \t]*#/ {if ($2 ~ /\//) print $2}' /etc/fstab )" -- "$cur" ) ) _linux_fstab < /etc/fstab
fi fi
fi fi
@ -62,12 +130,18 @@ complete -F _mount -o default -o dirnames mount
have umount && have umount &&
_umount() _umount()
{ {
local cur IFS=$'\n'
COMPREPLY=() COMPREPLY=()
cur=`_get_cword`
COMPREPLY=( $( compgen -W '$( mount | cut -d" " -f 3 )' -- "$cur" ) ) local cur=`_get_cword`
if [[ $(uname -s) = Linux && -r /proc/mounts ]]; then
# Linux /proc/mounts is properly quoted. This is important when
# unmounting usb devices with pretty names.
_linux_fstab < /proc/mounts
else
local IFS=$'\n'
COMPREPLY=( $( compgen -W '$( mount | cut -d" " -f 3 )' -- "$cur" ) )
fi
return 0 return 0
} && } &&

View File

@ -77,14 +77,14 @@ _perldoc()
shift splice unshift grep join map qw reverse sort unpack \ shift splice unshift grep join map qw reverse sort unpack \
delete each exists keys values binmode close closedir \ delete each exists keys values binmode close closedir \
dbmclose dbmopen die eof fileno flock format getc print \ dbmclose dbmopen die eof fileno flock format getc print \
printf read readdir rewinddir seek seekdir select syscall \ printf read readdir rewinddir say seek seekdir select syscall \
sysread sysseek syswrite tell telldir truncate warn write \ sysread sysseek syswrite tell telldir truncate warn write \
pack read syscall sysread syswrite unpack vec -X chdir chmod \ pack read syscall sysread syswrite unpack vec -X chdir chmod \
chown chroot fcntl glob ioctl link lstat mkdir open opendir \ chown chroot fcntl glob ioctl link lstat mkdir open opendir \
readlink rename rmdir stat symlink umask unlink utime caller \ readlink rename rmdir stat symlink umask unlink utime caller \
continue do dump eval exit goto last next redo return \ continue do dump eval exit goto last next redo return \
sub wantarray caller import local my our package use defined \ sub wantarray break caller import local my our state package \
formline reset scalar undef \ use defined formline reset scalar undef \
alarm exec fork getpgrp getppid getpriority kill pipe qx \ alarm exec fork getpgrp getppid getpriority kill pipe qx \
setpgrp setpriority sleep system times wait waitpid \ setpgrp setpriority sleep system times wait waitpid \
import no package require use bless dbmclose dbmopen package \ import no package require use bless dbmclose dbmopen package \
@ -98,7 +98,7 @@ _perldoc()
getnetbyaddr getnetbyname getnetent getprotobyname \ getnetbyaddr getnetbyname getnetent getprotobyname \
getprotobynumber getprotoent getservbyname getservbyport \ getprotobynumber getprotoent getservbyname getservbyport \
getservent sethostent setnetent setprotoent setservent \ getservent sethostent setnetent setprotoent setservent \
gmtime localtime time times' -- "$cur" ) ) gmtime localtime time times lock' -- "$cur" ) )
return 0 return 0
;; ;;
esac esac
@ -114,9 +114,10 @@ _perldoc()
sed -ne "/perl.*Perl overview/,/perlwin32/p" | \ sed -ne "/perl.*Perl overview/,/perlwin32/p" | \
awk "\$NF=2 { print \$1}" | command grep perl )' -- "$cur" ) ) awk "\$NF=2 { print \$1}" | command grep perl )' -- "$cur" ) )
fi fi
_filedir '@(pl|PL|pm|PM|pod|POD)'
fi fi
} }
complete -F _perldoc -o default perldoc complete -F _perldoc -o bashdefault perldoc
} }
# Local variables: # Local variables:

View File

@ -11,7 +11,7 @@ _removepkg()
COMPREPLY=( $( (cd /var/log/packages; compgen -f -- "$cur") ) ) COMPREPLY=( $( (cd /var/log/packages; compgen -f -- "$cur") ) )
} && } &&
complete -F _removepkg -o filenames removepkg && complete -F _removepkg -o filenames removepkg &&
complete -o dirnames -f -X '!*.tgz' installpkg upgradepkg explodepkg complete -o dirnames -f -X '!*.t[bglx]z' installpkg upgradepkg explodepkg
# Local variables: # Local variables:
# mode: shell-script # mode: shell-script

View File

@ -19,7 +19,7 @@ _tar()
return 0 return 0
;; ;;
+([^IZzJjy])f) +([^IZzJjy])f)
ext='t@(ar?(.@(Z|gz|bz?(2)|lz?(ma)))|gz|bz?(2)|lz?(ma))' ext='t@(ar?(.@(Z|gz|bz?(2)|lz?(ma)|xz))|gz|bz?(2)|lz?(ma)|xz)'
regex='t\(ar\(\.\(Z\|gz\|bz2\?\|lzma\|xz\)\)\?\|gz\|bz2\?\|lzma\|xz\)' regex='t\(ar\(\.\(Z\|gz\|bz2\?\|lzma\|xz\)\)\?\|gz\|bz2\?\|lzma\|xz\)'
;; ;;
*[Zz]*f) *[Zz]*f)

1
test/.gitignore vendored
View File

@ -1 +1,2 @@
dbg.log dbg.log
xtrace.log

24
test/fixtures/mount/test-fstab vendored Normal file
View File

@ -0,0 +1,24 @@
proc /proc proc defaults 0 0
none /debug debugfs defaults,noauto 0 0
# Simple obvious test.
/mnt/nice-test-path /dev/null auto ro,noauto 0 0
# Test octal escapes
# Contains ' ' and '-'
/mnt/nice\040test\055path /dev/null auto ro,noauto 0 0
# Contains '$' and '-'
/mnt/nice\044test\055path /dev/null auto ro,noauto 0 0
# Contains ' ' and '\\'
/mnt/nice\040test\134path /dev/null auto ro,noauto 0 0
# Contains '\n' and '\ '
/mnt/nice\012test\040path /dev/null auto ro,noauto 0 0
# Test apostrophe
/mnt/nice'test-path /dev/null auto ro,noauto 0 0
/mnt/other'test\040path /dev/null auto ro,noauto 0 0
# Test some labels
LABEL=Ubuntu\040Karmic /mnt/ubuntu auto no,noauto 0 0
LABEL=Fedora /mnt/fedora auto ro,noauto 0 0
LABEL=Debian-it's\040awesome /mnt/debian auto ro,noauto 0 0

View File

@ -2,16 +2,13 @@ source ${srcdir}/lib/library.exp
proc completion_exit {} { proc completion_exit {} {
# Exit bash
send "\rexit\r" send "\rexit\r"
}; # completion_exit() }
proc completion_start {} { proc completion_start {} {
start_bash start_interactive_test
source_bash_completion }
init_tcl_bash_globals
}; # completion_start()
proc completion_version {} { proc completion_version {} {

View File

@ -1,11 +1,38 @@
# mount completion from fstab can't be tested directly because it
# (correctly) uses absolute paths. So we create a custom completion which
# reads from a file in our text fixture instead.
proc setup_dummy_mnt {} {
assert_bash_exec {unset COMPREPLY cur}
assert_bash_exec {unset -f _mnt}
global TESTDIR
assert_bash_exec { \
_mnt() { \
local cur=$(_get_cword); \
_linux_fstab $(_get_pword) < "$TESTDIR/fixtures/mount/test-fstab"; \
}; \
complete -F _mnt mnt \
}
}
proc teardown_dummy_mnt {} {
assert_bash_exec {unset COMPREPLY cur}
assert_bash_exec {unset -f _mnt}
assert_bash_exec {complete -r mnt}
}
proc setup {} { proc setup {} {
save_env save_env
}; setup_dummy_mnt
}
proc teardown {} { proc teardown {} {
teardown_dummy_mnt
assert_env_unmodified assert_env_unmodified
}; }
setup setup
@ -30,4 +57,59 @@ assert_bash_exec {PATH="$OLDPATH"; unset -v OLDPATH}
sync_after_int sync_after_int
set test "Testing internal __linux_fstab_unescape function for mount"
# One round of slashes is for bash.
assert_bash_exec {var=one\'two\\040three\\}
assert_bash_exec {__linux_fstab_unescape var}
set cmd {echo $var}
send "$cmd\r"
expect {
-ex "$cmd\r\none'two three\\" { pass $test }
# default { fail $test }
}
sync_after_int
assert_bash_exec {unset var}
sync_after_int
# Begin testing through mnt (see setup_dummy_mnt).
assert_complete {/mnt/nice-test-path} {mnt /mnt/nice-test-p}
sync_after_int
assert_complete {/mnt/nice\ test-path} {mnt /mnt/nice\ test-p}
sync_after_int
assert_complete {/mnt/nice\$test-path} {mnt /mnt/nice\$test-p}
sync_after_int
assert_complete {/mnt/nice\ test\\path} {mnt /mnt/nice\ test\\p}
sync_after_int
assert_complete {{/mnt/nice\ test\\path} {/mnt/nice\ test-path}} \
{mnt /mnt/nice\ } "" /@ 20 {/mnt/nice\ }
sync_after_int
assert_complete {/mnt/nice\$test-path} {mnt /mnt/nice\$}
sync_after_int
assert_complete {/mnt/nice\'test-path} {mnt /mnt/nice\'}
sync_after_int
assert_complete {/mnt/other\'test\ path} {mnt /mnt/other}
sync_after_int
assert_complete {Ubuntu\ Karmic} {mnt -L Ubu}
sync_after_int
assert_complete {Debian-it\'s\ awesome} {mnt -L Deb}
sync_after_int
# This does not work. Proper support for this requires smarter parsing of
# $COMP_LINE and it's not worth doing just for mount.
#assert_complete {$'/mnt/nice\ntest-path'} {mnt $'/mnt/nice\n}
#sync_after_int
teardown teardown

View File

@ -112,7 +112,7 @@ if {[match_items [lsort -unique $expected] $test]} {
if {[lindex $::BASH_VERSINFO 0] >= 4} {xfail "$test"} {fail "$test"} if {[lindex $::BASH_VERSINFO 0] >= 4} {xfail "$test"} {fail "$test"}
}; # if }; # if
sync_after_int $prompt sync_after_int $prompt
assert_bash_exec "cd \$TESTDIR" assert_bash_exec {cd "$TESTDIR"}
sync_after_int sync_after_int

View File

@ -42,7 +42,7 @@ expect {
default { unresolved "$test" } default { unresolved "$test" }
}; # expect }; # expect
sync_after_int $prompt sync_after_int $prompt
assert_bash_exec "cd \$TESTDIR" assert_bash_exec {cd "$TESTDIR"}

View File

@ -71,7 +71,7 @@ expect {
default { unresolved "$test" } default { unresolved "$test" }
}; # expect }; # expect
sync_after_int $prompt sync_after_int $prompt
assert_bash_exec "cd \$TESTDIR" assert_bash_exec {cd "$TESTDIR"}
teardown teardown

View File

@ -29,7 +29,7 @@ expect {
default { unresolved "$test" } default { unresolved "$test" }
}; # expect }; # expect
sync_after_int $prompt sync_after_int $prompt
assert_bash_exec "cd \$TESTDIR" assert_bash_exec {cd "$TESTDIR"}
sync_after_int sync_after_int
@ -84,7 +84,7 @@ expect {
default { unresolved "$test" } default { unresolved "$test" }
}; # expect }; # expect
sync_after_int $prompt sync_after_int $prompt
assert_bash_exec "cd \$TESTDIR" assert_bash_exec {cd "$TESTDIR"}
sync_after_int sync_after_int

View File

@ -102,7 +102,7 @@ proc assert_bash_list_dir {expected cmd dir {test ""} {prompt /@} {size 20}} {
assert_bash_exec "cd $dir" "" $prompt assert_bash_exec "cd $dir" "" $prompt
assert_bash_list $expected $cmd $test $prompt $size assert_bash_list $expected $cmd $test $prompt $size
sync_after_int $prompt sync_after_int $prompt
assert_bash_exec "cd \$TESTDIR" assert_bash_exec {cd "$TESTDIR"}
}; # assert_bash_list_dir() }; # assert_bash_list_dir()
@ -272,7 +272,7 @@ proc assert_complete_dir {expected cmd dir {test ""} {size 20} {cword ""}} {
assert_bash_exec "cd $dir" "" $prompt assert_bash_exec "cd $dir" "" $prompt
assert_complete $expected $cmd $test $prompt $size $cword assert_complete $expected $cmd $test $prompt $size $cword
sync_after_int $prompt sync_after_int $prompt
assert_bash_exec "cd \$TESTDIR" assert_bash_exec {cd "$TESTDIR"}
}; # assert_complete_dir }; # assert_complete_dir
@ -692,16 +692,16 @@ proc save_env {{file ""}} {
# @param string File to save the environment to. Default is "$TESTDIR/tmp/env1~". # @param string File to save the environment to. Default is "$TESTDIR/tmp/env1~".
# @see assert_env_unmodified() # @see assert_env_unmodified()
proc _save_env {{file ""}} { proc _save_env {{file ""}} {
assert_bash_exec "{ set; declare -F; shopt -p; } > $file" assert_bash_exec "{ set; declare -F; shopt -p; } > \"$file\""
}; # _save_env() }; # _save_env()
# Source bash_completion package # Source bash_completion package
proc source_bash_completion {} { proc source_bash_completion {} {
assert_bash_exec {BASH_COMPLETION_DIR=$(cd $TESTDIR/..; pwd)/contrib} assert_bash_exec {BASH_COMPLETION_DIR=$(cd "$TESTDIR/.."; pwd)/contrib}
assert_bash_exec {BASH_COMPLETION_COMPAT_DIR=$BASH_COMPLETION_DIR} assert_bash_exec {BASH_COMPLETION_COMPAT_DIR=$BASH_COMPLETION_DIR}
assert_bash_exec {BASH_COMPLETION=$(cd $TESTDIR/..; pwd)/bash_completion} assert_bash_exec {BASH_COMPLETION=$(cd "$TESTDIR/.."; pwd)/bash_completion}
assert_bash_exec {source $BASH_COMPLETION} assert_bash_exec {source "$BASH_COMPLETION"}
}; # source_bash_completion() }; # source_bash_completion()
@ -829,6 +829,48 @@ proc start_bash {} {
}; # start_bash() }; # start_bash()
# Redirect xtrace output to a file.
#
# 'set -x' can be very useful for debugging but by default it writes to
# stderr. Bash 4.1 has a feature to redirect this output to a random FD.
#
# This function uses file descriptor 6. This will break if any completion
# tries to use the same descriptor.
proc init_bash_xtrace {{fname xtrace.log}} {
global BASH_VERSINFO
if {([lindex $BASH_VERSINFO 0] == 4 && [lindex $BASH_VERSINFO 1] < 1) ||
[lindex $BASH_VERSINFO 0] < 4} {
note "BASH_XTRACEFD not available in this version; no xtrace.log"
return
}
verbose "Enabling bash xtrace output to '$fname'"
assert_bash_exec "exec 6>'$fname'"
assert_bash_exec "BASH_XTRACEFD=6"
assert_bash_exec "set -o xtrace"
}
# Setup test environment
#
# Common initialization for unit and completion tests.
proc start_interactive_test {} {
start_bash
source_bash_completion
init_tcl_bash_globals
global OPT_BASH_XTRACE
if {[info exists OPT_BASH_XTRACE]} {
init_bash_xtrace
}
global OPT_TIMEOUT
if {[info exists OPT_TIMEOUT]} {
global timeout
verbose "Changing default expect timeout from $timeout to $OPT_TIMEOUT"
set timeout $OPT_TIMEOUT
}
}
# Interrupt completion and sync with prompt. # Interrupt completion and sync with prompt.
# Send signals QUIT & INT. # Send signals QUIT & INT.
# @param string $prompt (optional) Bash prompt. Default is "/@" # @param string $prompt (optional) Bash prompt. Default is "/@"
@ -836,13 +878,17 @@ proc sync_after_int {{prompt /@}} {
set test "Sync after INT" set test "Sync after INT"
sleep .1 sleep .1
send \031\003; # QUIT/INT send \031\003; # QUIT/INT
# NOTE: Regexp `.*' causes `expect' to discard previous unknown output. # Wait to allow bash to become ready
# This is necessary if a completion doesn't match expectations. # See also: http://lists.alioth.debian.org/pipermail/bash-completion-devel/
# For instance with `filetype_xspec' completion (e.g. `kdvi') if # 2010-February/002566.html
# one expects `.txt' as a completion (wrong, because it isn't sleep .1
# there), the unmatched completions need to be cleaned up. # NOTE: Regexp `.*' causes `expect' to discard previous unknown output.
# This is necessary if a completion doesn't match expectations.
# For instance with `filetype_xspec' completion (e.g. `kdvi') if
# one expects `.txt' as a completion (wrong, because it isn't
# there), the unmatched completions need to be cleaned up.
expect -re ".*$prompt$" expect -re ".*$prompt$"
}; # sync_after_int() }
proc sync_after_tab {} { proc sync_after_tab {} {

View File

@ -2,16 +2,14 @@ source lib/library.exp
proc unit_exit {} { proc unit_exit {} {
# Exit bash # Exit bash
send "\rexit\r" send "\rexit\r"
}; # unit_exit() }
proc unit_start {} { proc unit_start {} {
start_bash start_interactive_test
source_bash_completion }
init_tcl_bash_globals
}; # unit_start()
proc unit_version {} { proc unit_version {} {

View File

@ -1,31 +1,60 @@
#!/bin/bash #!/bin/bash
# Run test of specified tool.
# The first directory of the first file (first argument ending with .exp) is
# used as the `tool' specification.
# Usage: ./run [FILE]...
# Example run: ./run unit/_get_cword.exp unit/compgen.exp
# Process arguments # Print some helpful messages.
# @param $1 Name of variable to return `tool' name usage() {
# @param $2 Name of variable to return processed arguments echo "Run bash-completion tests"
# @param $@ Arguments to process echo
process_args() { echo "The 'tool' is determined automatically from filenames."
local arg echo "Unrecognized options are passed through to dejagnu by default."
for arg in "${@:3}"; do echo
case "$arg" in echo "Interesting options:"
completion/*.exp|unit/*.exp) echo " --tool_exec= Test against a different bash executable."
[[ ${!1} ]] || printf -v $1 "${arg%%/*}" echo " --debug Create a dbg.log in the test directory with detailed expect match information."
eval $2[\${#$2[@]}]=\""${arg#*/}"\" echo " --timeout Change expect timeout from the default of 10 seconds."
;; echo " --debug-xtrace Create an xtrace.log in the test directory with set -x output. Requires bash 4.1."
*) echo
eval $2[\${#$2[@]}]=\""$arg"\" echo "Example run: ./run unit/_get_cword.exp unit/compgen.exp"
esac
done
} }
args=()
process_args tool args "$@"
runtest --outdir log --tool $tool "${args[@]}"
unset -v args tool # Try to set the tool variable; or fail if trying to set different values.
set_tool() {
if [[ $tool ]]; then
if [[ $tool != $1 ]]; then
echo "Tool spec mismatch ('$tool' and '$1'). See --usage."
exit 1
fi
else
tool=$1
fi
}
cd "${BASH_SOURCE[0]%/*}"
# Loop over the arguments.
args=()
while [[ $# > 0 ]]; do
case "$1" in
--help|--usage) usage; exit 1;;
--debug-xtrace) args+=(OPT_BASH_XTRACE=1);;
--timeout) shift; timeout=$1;;
--timeout=*) timeout=${1/--timeout=};;
--tool=*) set_tool "${1#/--tool=}";;
--tool) shift; set_tool "$1";;
*/completion/*.exp|*/unit/*.exp)
arg=${1%/*}
set_tool "${arg##*/}"
args+=("${1##*/}")
;;
*) args+=("$1")
esac
shift
done
[[ -n $timeout ]] && args+=("OPT_TIMEOUT=$timeout")
[[ -z $tool ]] && { echo "Must specify tool somehow"; exit 1; }
runtest --outdir log --tool $tool "${args[@]}"

View File

@ -4,4 +4,4 @@
# isn't initialized at that point (i.e. output of `expect' is shown on # isn't initialized at that point (i.e. output of `expect' is shown on
# stdout - `open_logs' hasn't run yet?). And running code from a library # stdout - `open_logs' hasn't run yet?). And running code from a library
# file isn't probably a good idea either. # file isn't probably a good idea either.
runtest --outdir log --tool completion $* "${BASH_SOURCE[0]%/*}/run" --tool completion $*

View File

@ -4,4 +4,4 @@
# isn't initialized at that point (i.e. output of `expect' is shown on # isn't initialized at that point (i.e. output of `expect' is shown on
# stdout - `open_logs' hasn't run yet?). And running code from a library # stdout - `open_logs' hasn't run yet?). And running code from a library
# file isn't probably a good idea either. # file isn't probably a good idea either.
runtest --outdir log --tool unit $* "${BASH_SOURCE[0]%/*}/run" --tool unit $*

View File

@ -41,7 +41,7 @@ expect {
-re eof { unresolved "eof" } -re eof { unresolved "eof" }
}; # expect }; # expect
sync_after_int $prompt sync_after_int $prompt
assert_bash_exec "cd \$TESTDIR" assert_bash_exec {cd "$TESTDIR"}
#assert_bash_list_dir {a\\\'b/c} $cmd fixtures/compgen #assert_bash_list_dir {a\\\'b/c} $cmd fixtures/compgen