diff --git a/test/lib/completions/cd.exp b/test/lib/completions/cd.exp index c32e11c1..1361b3c6 100644 --- a/test/lib/completions/cd.exp +++ b/test/lib/completions/cd.exp @@ -39,7 +39,8 @@ set test "Tab should complete CDPATH" # Set CDPATH assert_bash_exec "declare -p CDPATH &>/dev/null && OLDCDPATH=\$CDPATH || :" assert_bash_exec "CDPATH=\$PWD"; -assert_complete "$::srcdir/fixtures/shared/default/foo.d/" "cd $::srcdir/fixtures/shared/default/fo" $test +assert_complete "$::srcdir/fixtures/shared/default/foo.d/" \ + "cd $::srcdir/fixtures/shared/default/fo" $test -nospace sync_after_int # Reset CDPATH assert_bash_exec "declare -p OLDCDPATH &>/dev/null && CDPATH=\$OLDCDPATH || unset CDPATH && unset OLDCDPATH" diff --git a/test/lib/completions/finger.exp b/test/lib/completions/finger.exp index f139c962..70e3ed2c 100644 --- a/test/lib/completions/finger.exp +++ b/test/lib/completions/finger.exp @@ -24,7 +24,7 @@ sync_after_int set test "Tab should complete partial username" -assert_complete_partial [exec bash -c "compgen -A user"] "finger" +assert_complete_partial [exec bash -c "compgen -A user"] "finger" -nospace sync_after_int diff --git a/test/lib/completions/ls.exp b/test/lib/completions/ls.exp index 5aafddb4..0d16ec03 100644 --- a/test/lib/completions/ls.exp +++ b/test/lib/completions/ls.exp @@ -24,7 +24,7 @@ set test "~part should complete to ~full/ if existing dir" assert_bash_exec {for u in $(compgen -u); do \ eval test -d ~$u && echo $u; unset u; done} {} /@ users find_unique_completion_pair $users part full -assert_complete "~$full/" "ls ~$part" $test +assert_complete "~$full/" "ls ~$part" $test -nospace sync_after_int @@ -35,7 +35,7 @@ set test "~part should complete to ~full if non-existing dir" assert_bash_exec {for u in $(compgen -u); do \ eval test -d ~$u || echo $u; unset u; done} {} /@ users find_unique_completion_pair $users part full -assert_complete "~$full " "ls ~$part" $test +assert_complete "~$full " "ls ~$part" $test -nospace sync_after_int diff --git a/test/lib/completions/ssh.exp b/test/lib/completions/ssh.exp index d16b5f98..217fa2c3 100644 --- a/test/lib/completions/ssh.exp +++ b/test/lib/completions/ssh.exp @@ -61,8 +61,8 @@ sync_after_int set test "First argument should complete partial hostname" -assert_complete_partial [get_hosts] ssh "" $test /@ 20 \ - [list "ltrim_colon_completions"] +assert_complete_partial [get_hosts] ssh "" $test \ + -filters "ltrim_colon_completions" sync_after_int diff --git a/test/lib/completions/sudo.exp b/test/lib/completions/sudo.exp index a4b7690a..d6bbbbb6 100644 --- a/test/lib/completions/sudo.exp +++ b/test/lib/completions/sudo.exp @@ -11,13 +11,14 @@ proc teardown {} { setup -assert_complete_dir foo.d/ "sudo cd fo" $::srcdir/fixtures/shared/default +assert_complete_dir foo.d/ "sudo cd fo" $::srcdir/fixtures/shared/default \ + "" -nospace sync_after_int -assert_complete_dir fixtures/ "sudo sh fix" $::srcdir +assert_complete_dir fixtures/ "sudo sh fix" $::srcdir "" -nospace sync_after_int diff --git a/test/lib/library.exp b/test/lib/library.exp index 7165509b..ace83dc9 100644 --- a/test/lib/library.exp +++ b/test/lib/library.exp @@ -89,15 +89,13 @@ proc assert_bash_list {expected cmd test {args {}}} { } else { send "$cmd\r" expect -ex "$cmd\r\n" - if {$arg(sort)} {set bash_sort "-bash-sort"} else {set bash_sort ""} + if {$arg(sort)} {set bash_sort "-bash-sort"} {set bash_sort ""} if {[ - match_items $expected $bash_sort -chunk-size $arg(chunk-size) \ - -prompt $prompt + eval match_items \$expected $bash_sort -chunk-size \ + \$arg(chunk-size) -end-newline -end-prompt \ + -prompt \$prompt ]} { - expect { - -re $prompt { pass "$test" } - -re eof { unresolved "eof" } - } + pass "$test" } else { fail "$test" } @@ -138,21 +136,34 @@ proc assert_bash_list_dir {expected cmd dir test {args {}}} { # command. # @param list $expected Expected completions. # @param string $cmd Command given to generate items -# @param string $test (optional) Test title. Default is "$cmd should show completions" -# @param string $prompt (optional) Bash prompt. Default is "/@" -# @param integer $size (optional) Chunk size. Default is 20. -# @param string $cword (optional) Last argument of $cmd which is an -# argument-to-complete and to be replaced with the longest common prefix -# of $expected. If empty string (default), `assert_complete' autodetects -# if the last argument is an argument-to-complete by checking if $cmd -# doesn't end with whitespace. Specifying `cword' should only be 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" +# @param string $test Test title +# @param list $args Options: +# -prompt PROMPT Bash prompt. Default is `/@' +# -chunk-size CHUNK-SIZE Compare list CHUNK-SIZE items at +# a time. Default is 20. +# -cword CWORD Last argument of $cmd which is an argument-to-complete and +# to be replaced with the longest common prefix of $expected. If empty +# string (default), `assert_complete' autodetects if the last argument +# is an argument-to-complete by checking if $cmd doesn't end with +# whitespace. Specifying `cword' should only be necessary if this +# autodetection fails, e.g. when the last whitespace is escaped or +# quoted, e.g. "finger foo\ " or "finger 'foo " +# -nospace Don't expect space character to be output after completion match. +# -filters List of filters to apply to this function to tweak the expected +# completions and argument-to-complete. Possible values: +# - "ltrim_colon_completions" +#proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""} {filters ""}} { # @result boolean True if successful, False if not -proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""} {filters ""}} { +proc assert_complete {expected cmd {test ""} {args {}}} { + array set arg [::cmdline::getoptions args { + {prompt.arg "/@" "bash prompt"} + {chunk-size.arg 20 "compare N list items at a time"} + {cword.arg "" "word to complete"} + {nospace "don't expect space after completion"} + {filters.arg "" "filters to preprocess expected completions"} + }] + set cword $arg(cword) + set prompt $arg(prompt) if {[llength $expected] == 0} { assert_no_complete $cmd $test } else { @@ -161,7 +172,7 @@ proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""} {f if {[llength $expected] == 1} { expect -ex "$cmd" - if {[lsearch -exact $filters "ltrim_colon_completions"] == -1} { + if {[lsearch -exact $arg(filters) "ltrim_colon_completions"] == -1} { set cur ""; # Default to empty word to complete on set words [split_words_bash $cmd] if {[llength $words] > 1} { @@ -180,20 +191,24 @@ proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""} {f set expected [lsort -unique $expected] } - if {[lsearch -exact $filters "ltrim_colon_completions"] != -1} { + if {[lsearch -exact $arg(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 {[match_items $expected -bash-sort -chunk-size $size -prompt $prompt]} { + if {$arg(nospace)} {set endspace ""} else {set endspace "-end-space"} + if {[ + eval match_items \$expected -bash-sort -chunk-size \ + \$arg(chunk-size) $endspace -prompt \$prompt + ]} { if {[llength $expected] == 1} { pass "$test" } else { # Remove optional (partial) last argument-to-complete from `cmd', # E.g. "finger test@" becomes "finger" - if {[lsearch -exact $filters "ltrim_colon_completions"] != -1} { + if {[lsearch -exact $arg(filters) "ltrim_colon_completions"] != -1} { set cmd2 $cmd } else { set cmd2 [_remove_cword_from_cmd $cmd $cword] @@ -290,15 +305,13 @@ proc assert_complete_any {cmd {test ""} {prompt /@}} { # @param list $expected # @param string $cmd Command given to generate items # @param string $dir Subdirectory to attempt completion in. The directory must be relative from the $TESTDIR and without a trailing slash. E.g. `fixtures/evince' -# @param string $test (optional) Test title. Default is "$cmd should show completions" -# @param string $prompt (optional) Bash prompt. Default is "/@" -# @param integer $size (optional) Chunk size. Default is 20. -# @param string $cword (optional) Last word of $cmd to complete. See: assert_complete() +# @param string $test Test title +# @param list $args See: assert_complete() # @result boolean True if successful, False if not -proc assert_complete_dir {expected cmd dir {test ""} {size 20} {cword ""}} { +proc assert_complete_dir {expected cmd dir {test ""} {args {}}} { set prompt "/@" assert_bash_exec "cd $dir" "" $prompt - assert_complete $expected $cmd $test $prompt $size $cword + assert_complete $expected $cmd $test $args sync_after_int $prompt assert_bash_exec {cd "$TESTDIR"} } @@ -312,14 +325,9 @@ proc assert_complete_dir {expected cmd dir {test ""} {size 20} {cword ""}} { # @param list $expected List of all completions. # @param string $cmd Command given to generate items # @param string $partial Word to complete -# @param string $test (optional) Test title. 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} {filters ""}} { +# @param string $test Test title +# @param list $args See: assert_complete() +proc assert_complete_partial {expected cmd {partial ""} {test ""} {args {}}} { if {$test == ""} {set test "$cmd should complete partial argument"} if {[llength $expected] == 0} { unresolved "$test" @@ -334,7 +342,7 @@ proc assert_complete_partial {expected cmd {partial ""} {test ""} {prompt /@} {s lappend pick $item } } - assert_complete $pick "$cmd $partial" $test $prompt $size $partial $filters + assert_complete $pick "$cmd $partial" $test $args } } @@ -637,12 +645,22 @@ proc is_cygwin {} { # -prompt PROMPT Bash prompt. Default is `/@' # -chunk-size CHUNK-SIZE Compare list CHUNK-SIZE items at # a time. Default is 20. +# -end-newline Expect newline after last item. +# Default is not. +# -end-prompt Expect prompt after last item. +# Default is not. +# -end-space Expect single space after last item. +# Default is not. Valid only if +# `end-newline' not set. # @result boolean True if successful, False if not proc match_items {items {args {}}} { array set arg [::cmdline::getoptions args { {bash-sort "compare list sorted"} {prompt.arg "/@" "bash prompt"} {chunk-size.arg 20 "compare N list items at a time"} + {end-newline "expect newline after last item"} + {end-prompt "expect prompt after last item"} + {end-space "expect space ater last item"} }] set prompt $arg(prompt) set size $arg(chunk-size) @@ -658,12 +676,20 @@ proc match_items {items {args {}}} { if {[llength $items] > 1} {append expected {\s+}} } if {[llength $items] == 1} { + if {$arg(end-prompt)} {set end $prompt} {set end ""} + # Both trailing space and newline are specified? + if {$arg(end-newline) && $arg(end-space)} { + # Indicate both trailing space or newline are ok + set expected2 "|^$expected $end$"; # Include space + append expected "\r\n$end"; # Include newline + } else { + if {$arg(end-newline)} {append expected "\r\n$end"} + if {$arg(end-space)} {append expected " $end"} + set expected2 "" + } expect { - -re "^$expected\r\n$" { set result true } - # NOTE: The optional space ( ?) depends on whether -o nospace is active - -re "^$expected ?$" { set result true } + -re "^$expected$$expected2" { set result true } -re "^$prompt$" {set result false; break } - "\r\n" { set result false; break } default { set result false; break } timeout { set result false; break } } diff --git a/test/unit/__expand_tilde_by_ref.exp b/test/unit/__expand_tilde_by_ref.exp index 000d3516..abd549cb 100644 --- a/test/unit/__expand_tilde_by_ref.exp +++ b/test/unit/__expand_tilde_by_ref.exp @@ -37,7 +37,7 @@ sync_after_int set test "~user should return /home/user" -set cmd [format {var="~%s"; __expand_tilde_by_ref var; printf "%%s" "$var"} $user] +set cmd [format {var="~%s"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user] assert_bash_list "$home" $cmd $test @@ -45,7 +45,7 @@ sync_after_int set test "~/foo should return /home/user/foo" -set cmd {var='~/foo'; __expand_tilde_by_ref var; printf "%s" "$var"} +set cmd {var='~/foo'; __expand_tilde_by_ref var; printf "%s\n" "$var"} assert_bash_list "$home/foo" $cmd $test @@ -53,7 +53,7 @@ sync_after_int set test "~user/bar should return /home/user/bar" -set cmd [format {var="~%s/bar"; __expand_tilde_by_ref var; printf "%%s" "$var"} $user] +set cmd [format {var="~%s/bar"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user] assert_bash_list "$home/bar" $cmd $test @@ -61,7 +61,7 @@ sync_after_int set test "~user/\$HOME should return /home/user/\$HOME" -set cmd [format {var="~%s/\$HOME"; __expand_tilde_by_ref var; printf "%%s" "$var"} $user] +set cmd [format {var="~%s/\$HOME"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user] assert_bash_list "$home/\$HOME" $cmd $test @@ -69,7 +69,7 @@ sync_after_int set test "'~user/a b' should return '/home/user/a b'" -set cmd [format {var="~%s/a b"; __expand_tilde_by_ref var; printf "%%s" "$var"} $user] +set cmd [format {var="~%s/a b"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user] assert_bash_list [list [format {%s/a b} $home]] $cmd $test @@ -77,7 +77,7 @@ sync_after_int set test "~user/* should return /home/user/*" -set cmd [format {var="~%s/*"; __expand_tilde_by_ref var; printf "%%s" "$var"} $user] +set cmd [format {var="~%s/*"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user] assert_bash_list "$home/\*" $cmd $test diff --git a/test/unit/_filedir.exp b/test/unit/_filedir.exp index 7c8c4205..de494084 100644 --- a/test/unit/_filedir.exp +++ b/test/unit/_filedir.exp @@ -118,7 +118,7 @@ foreach name {f f2} { set test "completing $name a\$ should return a\\\$b/" set cmd "$name a\$" - assert_complete_dir "\b\\\\\$b/" $cmd "$::srcdir/fixtures/_filedir" $test + assert_complete_dir "\b\\\\\$b/" $cmd "$::srcdir/fixtures/_filedir" $test -nospace sync_after_int diff --git a/test/unit/_get_comp_words_by_ref.exp b/test/unit/_get_comp_words_by_ref.exp index cb3f4dad..2ddcef23 100644 --- a/test/unit/_get_comp_words_by_ref.exp +++ b/test/unit/_get_comp_words_by_ref.exp @@ -247,7 +247,7 @@ sync_after_int set test "a -n| should return -n"; # | = cursor position set cmd {COMP_WORDS=(a -n); COMP_CWORD=1; COMP_LINE='a -n'; COMP_POINT=4} assert_bash_exec $cmd -set cmd {_get_comp_words_by_ref cur; printf %s $cur} +set cmd {_get_comp_words_by_ref cur; printf "%s\n" $cur} assert_bash_list -n $cmd $test diff --git a/test/unit/_get_cword.exp b/test/unit/_get_cword.exp index c3fbe2ae..ce749cec 100644 --- a/test/unit/_get_cword.exp +++ b/test/unit/_get_cword.exp @@ -30,7 +30,7 @@ sync_after_int set test "a b| should return b"; # | = cursor position -set cmd {COMP_WORDS=(a b); COMP_CWORD=1; COMP_LINE='a b'; COMP_POINT=3; _get_cword} +set cmd {COMP_WORDS=(a b); COMP_CWORD=1; COMP_LINE='a b'; COMP_POINT=3; _get_cword; echo} assert_bash_list b $cmd $test @@ -65,7 +65,7 @@ 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} +set cmd {COMP_WORDS=(a bc); COMP_CWORD=1; COMP_LINE='a bc'; COMP_POINT=3; _get_cword; echo} assert_bash_list b $cmd $test @@ -73,7 +73,7 @@ sync_after_int set test {a b\ c| should return b\ c}; # | = cursor position -set cmd {COMP_WORDS=(a 'b\ c'); COMP_CWORD=1; COMP_LINE='a b\ c'; COMP_POINT=6; _get_cword} +set cmd {COMP_WORDS=(a 'b\ c'); COMP_CWORD=1; COMP_LINE='a b\ c'; COMP_POINT=6; _get_cword; echo} assert_bash_list {"b\\ c"} $cmd $test @@ -81,7 +81,7 @@ sync_after_int set test {a b\| c should return b\ }; # | = cursor position -set cmd {COMP_WORDS=(a 'b\ c'); COMP_CWORD=1; COMP_LINE='a b\ c'; COMP_POINT=4; _get_cword} +set cmd {COMP_WORDS=(a 'b\ c'); COMP_CWORD=1; COMP_LINE='a b\ c'; COMP_POINT=4; _get_cword; echo} assert_bash_list {"b\\"} $cmd $test @@ -89,7 +89,7 @@ sync_after_int set test {a "b\| should return "b\ }; # | = cursor position -set cmd {COMP_WORDS=(a '"b\'); COMP_CWORD=1; COMP_LINE='a "b\'; COMP_POINT=5; _get_cword} +set cmd {COMP_WORDS=(a '"b\'); COMP_CWORD=1; COMP_LINE='a "b\'; COMP_POINT=5; _get_cword; echo} assert_bash_list {"\"b\\"} $cmd $test @@ -160,7 +160,7 @@ if {[lindex $::BASH_VERSINFO 0] <= 3} { set cmd {add_comp_wordbreak_char :; COMP_WORDS=(a b : c); COMP_CWORD=3} set expected c } -append cmd {; COMP_LINE='a b:c'; COMP_POINT=5; _get_cword} +append cmd {; COMP_LINE='a b:c'; COMP_POINT=5; _get_cword; echo} assert_bash_list $expected $cmd $test @@ -173,7 +173,7 @@ if {[lindex $::BASH_VERSINFO 0] <= 3} { } else { set cmd {COMP_WORDS=(a b : c); COMP_CWORD=3} } -append cmd {; COMP_LINE='a b:c'; COMP_POINT=5; _get_cword :} +append cmd {; COMP_LINE='a b:c'; COMP_POINT=5; _get_cword :; echo} assert_bash_list b:c $cmd $test @@ -186,7 +186,7 @@ if {[lindex $::BASH_VERSINFO 0] <= 3} { } else { set cmd {COMP_WORDS=(a b c :); COMP_CWORD=3} } -append cmd {; COMP_LINE='a b c:'; COMP_POINT=6; _get_cword :} +append cmd {; COMP_LINE='a b c:'; COMP_POINT=6; _get_cword :; echo} assert_bash_list c: $cmd $test @@ -194,7 +194,7 @@ 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 :} +set cmd {COMP_WORDS=(a :); COMP_CWORD=1; COMP_LINE='a :'; COMP_POINT=3; _get_cword :; echo} assert_bash_list : $cmd $test @@ -207,7 +207,7 @@ if {[lindex $::BASH_VERSINFO 0] <= 3} { } else { set cmd {COMP_WORDS=(a b ::); COMP_CWORD=2} } -append cmd {; COMP_LINE='a b::'; COMP_POINT=5; _get_cword :} +append cmd {; COMP_LINE='a b::'; COMP_POINT=5; _get_cword :; echo} assert_bash_list b:: $cmd $test @@ -217,7 +217,7 @@ sync_after_int # This test makes sure `_get_cword' doesn't use `echo' to return it's value, # because -n might be interpreted by `echo' and thus will not be returned. set test "a -n| should return -n"; # | = cursor position -set cmd {COMP_WORDS=(a -n); COMP_CWORD=1; COMP_LINE='a -n'; COMP_POINT=4; _get_cword} +set cmd {COMP_WORDS=(a -n); COMP_CWORD=1; COMP_LINE='a -n'; COMP_POINT=4; _get_cword; echo} assert_bash_list -n $cmd $test @@ -225,7 +225,7 @@ sync_after_int set test {a b>c| should return c}; # | = cursor position -set cmd {COMP_WORDS=(a b \> c); COMP_CWORD=3; COMP_LINE='a b>c'; COMP_POINT=5; _get_cword} +set cmd {COMP_WORDS=(a b \> c); COMP_CWORD=3; COMP_LINE='a b>c'; COMP_POINT=5; _get_cword; echo} assert_bash_list c $cmd $test @@ -240,7 +240,7 @@ if {[lindex $::BASH_VERSINFO] <= 3} { set cmd {COMP_WORDS=(a b = c); COMP_CWORD=3} set expected c } -append cmd {; COMP_LINE='a b=c'; COMP_POINT=5; _get_cword} +append cmd {; COMP_LINE='a b=c'; COMP_POINT=5; _get_cword; echo} assert_bash_list $expected $cmd $test @@ -248,7 +248,7 @@ sync_after_int set test {a *| should return *}; # | = cursor position -set cmd {COMP_WORDS=(a \*); COMP_CWORD=1; COMP_LINE='a *'; COMP_POINT=4; _get_cword} +set cmd {COMP_WORDS=(a \*); COMP_CWORD=1; COMP_LINE='a *'; COMP_POINT=4; _get_cword; echo} assert_bash_list * $cmd $test diff --git a/test/unit/_tilde.exp b/test/unit/_tilde.exp index 54394cb8..2e22b848 100644 --- a/test/unit/_tilde.exp +++ b/test/unit/_tilde.exp @@ -36,7 +36,7 @@ sync_after_int set test "~full should complete to ~full unmodified" -set cmd [format {_tilde "~%s"; printf "%%s" "${COMPREPLY[@]}"} $full] +set cmd [format {_tilde "~%s"; printf "%%s\n" "${COMPREPLY[@]}"} $full] assert_bash_list "~$full" $cmd $test @@ -44,7 +44,7 @@ sync_after_int set test "~part should complete to ~full" -set cmd [format {_tilde "~%s"; printf "%%s" "${COMPREPLY[@]}"} $part] +set cmd [format {_tilde "~%s"; printf "%%s\n" "${COMPREPLY[@]}"} $part] assert_bash_list "~$full" $cmd $test