From 3251038c9da5ba469f85870fac05ff6e3a4b7852 Mon Sep 17 00:00:00 2001 From: Freddy Vulto Date: Wed, 30 Dec 2009 09:43:16 +0100 Subject: [PATCH 1/5] Fix __reassemble_comp_words_by_ref() On bash-3, completing a b c: with COMP_WORDBREAKS -= : would result in the current word being bc: (Alioth #312190) Added unit test, run via: ./run unit/_get_cword.exp --- bash_completion | 4 ++-- test/unit/_get_cword.exp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/bash_completion b/bash_completion index 248bd25a..7d313a66 100644 --- a/bash_completion +++ b/bash_completion @@ -228,8 +228,8 @@ __reassemble_comp_words_by_ref() { # 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 made up of - # just word separators characters to be excluded? - while [[ $i -gt 0 && ${COMP_WORDS[$i]//[^$exclude]} ]]; do + # just word separator characters to be excluded? + while [[ $i -gt 0 && ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]} ]]; do [ $j -ge 2 ] && ((j--)) # Append word separator to current word ref="$2[$j]" diff --git a/test/unit/_get_cword.exp b/test/unit/_get_cword.exp index 7e38e9ed..f71971b4 100644 --- a/test/unit/_get_cword.exp +++ b/test/unit/_get_cword.exp @@ -161,6 +161,19 @@ assert_bash_list b:c $cmd $test sync_after_int +set test {a b c:| with WORDBREAKS -= : should return c:}; # | = 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} +}; # if +append cmd {; COMP_LINE='a b c:'; COMP_POINT=6; _get_cword :} +assert_bash_list c: $cmd $test + + +sync_after_int + + set test {a :| with WORDBREAKS -= : should return :}; # | = cursor position set cmd {COMP_WORDS=(a :); COMP_CWORD=1; COMP_LINE='a :'; COMP_POINT=3; _get_cword :} assert_bash_list : $cmd $test From f321c377affad39214c5cff02b66090f49232abe Mon Sep 17 00:00:00 2001 From: Freddy Vulto Date: Wed, 30 Dec 2009 14:48:17 +0100 Subject: [PATCH 2/5] (testsuite) Delete directory fixtures/_filedir/a\b Directories `a\b' and `a*b' are now created run-time on a non-Cygwin/Windows system only. Tests concerning these directories will also be run only on a non-Cygwin/Windows system. (Alioth #312191) --- "test/fixtures/_filedir/a\\b/g" | 0 test/lib/library.exp | 26 ++++++++++++-------- test/unit/_filedir.exp | 42 +++++++++++++++++++++++---------- 3 files changed, 45 insertions(+), 23 deletions(-) delete mode 100644 "test/fixtures/_filedir/a\\b/g" diff --git "a/test/fixtures/_filedir/a\\b/g" "b/test/fixtures/_filedir/a\\b/g" deleted file mode 100644 index e69de29b..00000000 diff --git a/test/lib/library.exp b/test/lib/library.exp index 968d7809..1af23f32 100644 --- a/test/lib/library.exp +++ b/test/lib/library.exp @@ -417,6 +417,16 @@ proc assert_exec {cmd {stdout ''} {test ''}} { }; # assert_exec() +# Sort list. +# `exec sort' is used instead of `lsort' to achieve exactly the +# same sort order as in bash. +# @param list $items +# @return list Sort list +proc bash_sort {items} { + return [split [exec sort << [join $items "\n"]] "\n"] +}; # bash_sort() + + # Get hostnames # @return list Hostnames proc get_hosts {} { @@ -467,16 +477,6 @@ proc get_signals {} { }; # get_signals() -# Sort list. -# `exec sort' is used instead of `lsort' to achieve exactly the -# same sort order as in bash. -# @param list $items -# @return list Sort list -proc bash_sort {items} { - return [split [exec sort << [join $items "\n"]] "\n"] -}; # bash_sort() - - # Initialize tcl globals with bash variables proc init_tcl_bash_globals {} { global BASH_VERSINFO BASH_VERSION COMP_WORDBREAKS @@ -488,6 +488,12 @@ proc init_tcl_bash_globals {} { }; # init_tcl_bash_globals() +# Detect if test suite is running under Cygwin/Windows +proc is_cygwin {} { + expr {[string first [string tolower [exec uname -s]] cygwin] >= 0} +}; # is_cygwin() + + # Expect items. # Break items into chunks because `expect' seems to have a limited buffer size # @param list $items diff --git a/test/unit/_filedir.exp b/test/unit/_filedir.exp index c5dd877e..2e4591e8 100644 --- a/test/unit/_filedir.exp +++ b/test/unit/_filedir.exp @@ -11,15 +11,22 @@ proc setup {} { 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)} + # Create directories `a*b' and `a\b' only when not running on Cygwin/Windows; + # directories containing `*' or `\' aren't allowed on Cygwin/Windows + if {! [is_cygwin]} { + # Create directory `a*b' + assert_bash_exec {(cd fixtures/_filedir && [ ! -d a\*b ] && mkdir a\*b && touch a\*b/j || true)} + # Create directory `a\b' + assert_bash_exec {(cd fixtures/_filedir && [ ! -d a\\b ] && mkdir a\\b && touch a\\b/g || true)} + }; # if }; # setup() proc teardown {} { - assert_bash_exec {(cd fixtures/_filedir && rm -- a\*b/j && rmdir a\*b/ || true)} + if {! [is_cygwin]} { + assert_bash_exec {(cd fixtures/_filedir && rm -- a\\b/g && rmdir a\\b/ || true)} + assert_bash_exec {(cd fixtures/_filedir && rm -- a\*b/j && rmdir a\*b/ || true)} + }; # if assert_bash_exec {unset COMPREPLY cur} assert_bash_exec {unset -f _f} assert_bash_exec {complete -r f} @@ -79,12 +86,17 @@ foreach name {f f2} { sync_after_int - set test "completing $name a\\\\b/ should return g" - set cmd "$name a\\\\b/" - assert_complete_dir g $cmd "fixtures/_filedir" + # Execute these tests only when not running on Cygwin/Windows, because + # directories containing asterisk (*) or backslash (\) aren't allowed on + # Cygwin/Windows + if {! [is_cygwin]} { + set test "completing $name a\\\\b/ should return g" + set cmd "$name a\\\\b/" + assert_complete_dir g $cmd "fixtures/_filedir" - sync_after_int + sync_after_int + }; # if set test "completing $name a\\&b/ should return f" @@ -147,12 +159,16 @@ foreach name {f f2} { sync_after_int - set test "completing $name 'a\\b/ should return g" - set cmd "$name 'a\\b/" - assert_complete_dir {g'} $cmd "fixtures/_filedir" + # Execute these tests only when not running on Cygwin/Windows, because + # directories containing `*' or `\' aren't allowed on Cygwin/Windows + if {! [is_cygwin]} { + set test "completing $name 'a\\b/ should return g" + set cmd "$name 'a\\b/" + assert_complete_dir {g'} $cmd "fixtures/_filedir" - sync_after_int + sync_after_int + }; # if set test "completing $name 'a&b/ should return f" From 9c402241c485ec6dea0915e071f70db2b2107246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Wed, 30 Dec 2009 22:59:17 +0200 Subject: [PATCH 3/5] Add rtcwake completion. --- CHANGES | 4 ++-- Makefile.am | 1 + contrib/rtcwake | 39 ++++++++++++++++++++++++++++++++ test/completion/rtcwake.exp | 3 +++ test/lib/completions/rtcwake.exp | 20 ++++++++++++++++ 5 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 contrib/rtcwake create mode 100644 test/completion/rtcwake.exp create mode 100644 test/lib/completions/rtcwake.exp diff --git a/CHANGES b/CHANGES index c76677a6..399f4344 100644 --- a/CHANGES +++ b/CHANGES @@ -29,8 +29,8 @@ bash-completion (2.x) mysqladmin, rsync, screen, service, scp, ssh, sshfs, update-alternatives, vncviewer, and general hostname completions. * Add abook and wtf completion, based on work by Raphaƫl Droz. - * Add cvsps, fusermount, jarsigner, k3b, lftpget, pm-utils, pack200 and - unpack200 completions. + * Add cvsps, fusermount, jarsigner, k3b, lftpget, pm-utils, rtcwake, pack200 + and unpack200 completions. * Don't overwrite other host completions when completing from multiple SSH known hosts files. * Speed up installed rpm package completion on SUSE, based on work by diff --git a/Makefile.am b/Makefile.am index 06309d33..db0fbab9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -117,6 +117,7 @@ bashcomp_DATA = contrib/abook \ contrib/rpmcheck \ contrib/rrdtool \ contrib/rsync \ + contrib/rtcwake \ contrib/samba \ contrib/sbcl \ contrib/screen \ diff --git a/contrib/rtcwake b/contrib/rtcwake new file mode 100644 index 00000000..42637e6f --- /dev/null +++ b/contrib/rtcwake @@ -0,0 +1,39 @@ +# bash completion for rtcwake + +have rtcwake && +_rtcwake() +{ + COMPREPLY=() + local cur=`_get_cword` prev=`_get_pword` split=false + + _split_longopt && split=true + + case "$prev" in + --help|-h|--version|-V|--seconds|-s|--time|-t) + return 0 + ;; + --mode|-m) + COMPREPLY=( $( compgen -W 'standby mem disk on no off' -- "$cur" ) ) + return 0 + ;; + --device|-d) + COMPREPLY=( $( command ls -d /dev/rtc* 2>/dev/null ) ) + COMPREPLY=( $( compgen -W '${COMPREPLY[@]#/dev/}' -- "$cur" ) ) + return 0 + ;; + esac + + $split && return 0 + + COMPREPLY=( $( compgen -W '--device --local --mode --seconds --time --utc \ + --verbose --version --help' -- "$cur" ) ) +} && +complete -F _rtcwake rtcwake + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff --git a/test/completion/rtcwake.exp b/test/completion/rtcwake.exp new file mode 100644 index 00000000..3970a42a --- /dev/null +++ b/test/completion/rtcwake.exp @@ -0,0 +1,3 @@ +if {[assert_bash_type rtcwake]} { + source "lib/completions/rtcwake.exp" +}; # if diff --git a/test/lib/completions/rtcwake.exp b/test/lib/completions/rtcwake.exp new file mode 100644 index 00000000..0b9a974b --- /dev/null +++ b/test/lib/completions/rtcwake.exp @@ -0,0 +1,20 @@ +proc setup {} { + save_env +}; # setup() + + +proc teardown {} { + assert_env_unmodified +}; # teardown() + + +setup + + +assert_complete_any "rtcwake " + + +sync_after_int + + +teardown From 07db41e38f5d4da5499cc3eec6dfe01fb738c415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Wed, 30 Dec 2009 23:05:29 +0200 Subject: [PATCH 4/5] Don't list non-working "rtc" in --device completions. --- contrib/rtcwake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/rtcwake b/contrib/rtcwake index 42637e6f..0169fb61 100644 --- a/contrib/rtcwake +++ b/contrib/rtcwake @@ -17,7 +17,7 @@ _rtcwake() return 0 ;; --device|-d) - COMPREPLY=( $( command ls -d /dev/rtc* 2>/dev/null ) ) + COMPREPLY=( $( command ls -d /dev/rtc?* 2>/dev/null ) ) COMPREPLY=( $( compgen -W '${COMPREPLY[@]#/dev/}' -- "$cur" ) ) return 0 ;; From 3f0bfbc5aea5efb1d9b20384e8291d9785bf3ae0 Mon Sep 17 00:00:00 2001 From: Freddy Vulto Date: Thu, 31 Dec 2009 11:12:15 +0100 Subject: [PATCH 5/5] Fix __reassemble_comp_words_by_ref() Completing "a b " returned cur=b instead of cur=nothing if a wordbreak character was specified. --- bash_completion | 14 +++++++++----- test/unit/_get_cword.exp | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/bash_completion b/bash_completion index 7d313a66..0747fd66 100644 --- a/bash_completion +++ b/bash_completion @@ -222,14 +222,19 @@ __reassemble_comp_words_by_ref() { exclude="${1//[^$COMP_WORDBREAKS]}" fi + # Default to cword unchanged + eval $3=$COMP_CWORD # Are characters excluded which were former included? if [[ $exclude ]]; then # Yes, list of word completion separators has shrunk; # 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 made up of - # just word separator characters to be excluded? - while [[ $i -gt 0 && ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]} ]]; 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? + while [[ $i -gt 0 && ${COMP_WORDS[$i]} && + ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]} + ]]; do [ $j -ge 2 ] && ((j--)) # Append word separator to current word ref="$2[$j]" @@ -243,12 +248,11 @@ __reassemble_comp_words_by_ref() { ref="$2[$j]" eval $2[$j]=\${!ref}\${COMP_WORDS[i]} # Indicate new cword - [ $i = $COMP_CWORD ] && eval $3=$j + [ $i = $COMP_CWORD ] && [[ ${COMP_WORDS[i]} ]] && eval $3=$j done else # No, list of word completions separators hasn't changed; eval $2=\( \"\${COMP_WORDS[@]}\" \) - eval $3=$COMP_CWORD fi } # __reassemble_comp_words_by_ref() diff --git a/test/unit/_get_cword.exp b/test/unit/_get_cword.exp index f71971b4..25e0e8d5 100644 --- a/test/unit/_get_cword.exp +++ b/test/unit/_get_cword.exp @@ -45,6 +45,24 @@ expect -ex "$cmd\r\n/@" {pass "$test"} sync_after_int +set test "a b | should return nothing"; # | = cursor position +set cmd {COMP_WORDS=(a b ''); COMP_CWORD=2; COMP_LINE='a b '; COMP_POINT=4; _get_cword} +send "$cmd\r" +expect -ex "$cmd\r\n/@" {pass "$test"} + + +sync_after_int + + +set test "a b | with WORDBREAKS -= : should return nothing"; # | = cursor position +set cmd {COMP_WORDS=(a b ''); COMP_CWORD=2; COMP_LINE='a b '; COMP_POINT=4; _get_cword :} +send "$cmd\r" +expect -ex "$cmd\r\n/@" {pass "$test"} + + +sync_after_int + + set test "a b|c should return b"; # | = cursor position set cmd {COMP_WORDS=(a bc); COMP_CWORD=1; COMP_LINE='a bc'; COMP_POINT=3; _get_cword} assert_bash_list b $cmd $test