diff --git a/test/lib/completion.exp b/test/lib/completion.exp index 299f2691..c7efff66 100644 --- a/test/lib/completion.exp +++ b/test/lib/completion.exp @@ -8,7 +8,7 @@ proc completion_exit {} { proc completion_start {} { - global bash_versinfo_0 TESTDIR TOOL_EXECUTABLE spawn_id + global bash_versinfo_0 COMP_WORDBREAKS TESTDIR TOOL_EXECUTABLE spawn_id set test "completion_start" set TESTDIR [pwd] @@ -23,6 +23,7 @@ proc completion_start {} { assert_bash_exec {source $BASH_COMPLETION} # Fill global var `bash_versinfo_0' with bash major version number assert_bash_exec {printf "%s" "${BASH_VERSINFO[0]}"} "" /@ bash_versinfo_0 + assert_bash_exec {printf "%s" "$COMP_WORDBREAKS"} "" /@ COMP_WORDBREAKS }; # completion_start() diff --git a/test/lib/completions/ssh.exp b/test/lib/completions/ssh.exp index 6afd3397..c3341294 100644 --- a/test/lib/completions/ssh.exp +++ b/test/lib/completions/ssh.exp @@ -75,7 +75,7 @@ sync_after_int set test "First argument should complete partial hostname" -assert_complete_partial [get_hosts] ssh +assert_complete_partial [get_hosts] ssh "" $test /@ 20 [list "ltrim_colon_completions"] sync_after_int diff --git a/test/lib/library.exp b/test/lib/library.exp index 730e98ba..7a13b9fa 100644 --- a/test/lib/library.exp +++ b/test/lib/library.exp @@ -109,21 +109,26 @@ proc assert_bash_list {expected cmd {test ""} {prompt /@} {size 20}} { # doesn't end with whitespace. Specifying `cword' is only necessary if # this autodetection fails, e.g. when the last whitespace is escaped or # quoted, e.g. "finger foo\ " or "finger 'foo " +# @param list $filters (optional) List of filters to apply to this function to tweak +# the expected completions and argument-to-complete. Possible values: +# - "ltrim_colon_completions" # @result boolean True if successful, False if not -proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""}} { +proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""} {filters ""}} { if {$test == ""} {set test "$cmd should show completions"} send "$cmd\t" if {[llength $expected] == 1} { expect -ex "$cmd" - set cmds [split $cmd] - set cur ""; # Default to empty word to complete on - if {[llength $cmds] > 1} { - # Assume last word of `$cmd' is word to complete on. - set cur [lindex $cmds [expr [llength $cmds] - 1]] - }; # if - # Remove second word from beginning of single item $expected - if {[string first $cur $expected] == 0} { - set expected [string range $expected [string length $cur] end] + if {[lsearch -exact $filters "ltrim_colon_completions"] == -1} { + set cmds [split $cmd] + set cur ""; # Default to empty word to complete on + if {[llength $cmds] > 1} { + # Assume last word of `$cmd' is word to complete on. + set cur [lindex $cmds [expr [llength $cmds] - 1]] + }; # if + # Remove second word from beginning of single item $expected + if {[string first $cur $expected] == 0} { + set expected [string range $expected [string length $cur] end] + }; # if }; # if } else { expect -ex "$cmd\r\n" @@ -131,6 +136,12 @@ proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""}} { set expected [lsort -unique $expected] }; # if + if {[lsearch -exact $filters "ltrim_colon_completions"] != -1} { + # If partial contains colon (:), remove partial from begin of items + # See also: bash_completion.__ltrim_colon_completions() + _ltrim_colon_completions cword expected + }; # if + if {[match_items $expected $test]} { if {[llength $expected] == 1} { pass "$test" @@ -138,7 +149,12 @@ proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""}} { # Remove optional (partial) last argument-to-complete from `cmd', # E.g. "finger test@" becomes "finger" - set cmd2 [_remove_cword_from_cmd $cmd $cword] + if {[lsearch -exact $filters "ltrim_colon_completions"] != -1} { + set cmd2 $cmd + } else { + set cmd2 [_remove_cword_from_cmd $cmd $cword] + }; # if + # Determine common prefix of completions set common [::textutil::string::longestCommonPrefixList $expected] #if {[string length $common] > 0} {set common " $common"} @@ -249,8 +265,11 @@ proc assert_complete_dir {expected cmd dir {test ""} {size 20} {cword ""}} { # @param string $test (optional) Test titel. Default is "$cmd should show completions" # @param string $prompt (optional) Bash prompt. Default is "/@" # @param integer $size (optional) Chunk size. Default is 20. +# @param list $filters (optional) List of filters to apply to this function to tweak +# the expected completions and argument-to-complete. +# @see assert_complete() # @result boolean True if successful, False if not -proc assert_complete_partial {expected cmd {partial ""} {test ""} {prompt /@} {size 20}} { +proc assert_complete_partial {expected cmd {partial ""} {test ""} {prompt /@} {size 20} {filters ""}} { if {$test == ""} {set test "$cmd should complete partial argument"} if {[llength $expected] == 0} { unresolved "$test" @@ -265,11 +284,36 @@ proc assert_complete_partial {expected cmd {partial ""} {test ""} {prompt /@} {s lappend pick $item }; # if }; # foreach - assert_complete $pick "$cmd $partial" $test $prompt $size $partial + assert_complete $pick "$cmd $partial" $test $prompt $size $partial $filters }; # if }; # assert_complete_partial() +# See also: bash_completion._ltrim_colon_completions +proc _ltrim_colon_completions {cword items} { + upvar 1 $cword cword_out + upvar 1 $items items_out + # If word-to-complete contains a colon, + # and bash-version < 4, + # or bash-version >= 4 and COMP_WORDBREAKS contains a colon + if { + [string first : $cword_out] > -1 && ( + $::bash_versinfo_0 < 4 || + ($::bash_versinfo_0 >= 4 && [string first ":" $::COMP_WORDBREAKS] > -1) + ) + } { + for {set i 0} {$i < [llength $items_out]} {incr i} { + set item [lindex $items_out $i] + if {[string first $cword_out $item] == 0} { + # Strip colon-prefix + lset items_out $i [string range $item [string length $cword_out] end] + }; # if + }; # for + #set cword_out "" + }; # if +}; # _ltrim_colon_completions() + + # Make sure the bash environment hasn't changed between now and the last call # to `save_env()'. # @param string $sed Sed commands to preprocess diff output. @@ -422,6 +466,7 @@ proc get_signals {} { proc match_items {items test {size 20}} { # NOTE: `exec sort' is used instead of `lsort' to achieve exactly the # same sort order as in bash -- FVu, Wed Nov 25 22:25:28 CET 2009 + #set items [list [exec sort << [join $items "\n"]]] set items [exec sort << [join $items "\n"]] set result false for {set i 0} {$i < [llength $items]} {set i [expr {$i + $size}]} { diff --git a/test/lib/unit.exp b/test/lib/unit.exp index 14e64cca..36096c07 100644 --- a/test/lib/unit.exp +++ b/test/lib/unit.exp @@ -8,7 +8,7 @@ proc unit_exit {} { proc unit_start {} { - global bash_versinfo_0 TESTDIR TOOL_EXECUTABLE spawn_id + global bash_versinfo_0 COMP_WORDBREAKS TESTDIR TOOL_EXECUTABLE spawn_id set test "unit_start" set TESTDIR [pwd] @@ -29,6 +29,7 @@ proc unit_start {} { assert_bash_exec {source $BASH_COMPLETION} # Fill global var `bash_versinfo_0' with bash major version number assert_bash_exec {printf "%s" "${BASH_VERSINFO[0]}"} "" /@ bash_versinfo_0 + assert_bash_exec {printf "%s" "$COMP_WORDBREAKS"} {} /@ COMP_WORDBREAKS }; # unit_start()