100
proc assert_bash_list_dir {expected cmd dir {test ""} {prompt /@} {size 20}} {
106
# Make sure the expected list matches the real list, as returned by executing
107
# the specified bash command within the specified directory.
108
# Specify `-sort' if the real list is sorted.
109
# @param list $expected Expected list items
110
# @param string $cmd Bash command to generate real list items
111
# @param string $dir Directory to execute $cmd within
112
# @param string $test Test title. Becomes "$cmd should show expected output"
114
# @param list $args Options:
115
# -sort Compare list sorted. Default is unsorted
116
# -prompt Bash prompt. Default is `/@'
117
# -chunk-size N Compare list N items at a time. Default
119
proc assert_bash_list_dir {expected cmd dir test {args {}}} {
120
array set arg [::cmdline::getoptions args {
121
{sort "compare list sorted"}
122
{prompt.arg "/@" "bash prompt"}
123
{chunk-size.arg 20 "compare N list items at a time"}
125
set prompt $arg(prompt)
126
if {$arg(sort)} {set arg_sort "-sort"} else {set arg_sort ""}
102
127
assert_bash_exec "cd $dir" "" $prompt
103
assert_bash_list $expected $cmd $test $prompt $size
128
assert_bash_list $expected $cmd $test $arg_sort \
129
-chunk-size $arg(chunk-size) -prompt $prompt
104
130
sync_after_int $prompt
105
131
assert_bash_exec {cd "$TESTDIR"}
106
}; # assert_bash_list_dir()
109
135
# Make sure the expected items are returned by TAB-completing the specified
136
# command. If the number of expected items is one, expected is:
138
# $cmd<TAB>$expected[<SPACE>]
140
# SPACE is not expected if -nospace is specified.
142
# If the number of expected items is greater than one, expected is:
146
# $prompt + ($cmd - AUTO) + longest-common-prefix-of-$expected
148
# AUTO is calculated like this: If $cmd ends with non-whitespace, and
149
# the last argument of $cmd equals the longest-common-prefix of
150
# $expected, $cmd minus this argument will be expected.
152
# If the algorithm above fails, you can manually specify the CWORD to be
153
# subtracted from $cmd specifying `-expect-cmd-minus CWORD'. Known cases where
154
# this is useful are when:
155
# - the last whitespace is escaped, e.g. "finger foo\ " or "finger
158
# If the entire $cmd is expected, specify `-expect-cmd-full'.
111
160
# @param list $expected Expected completions.
112
161
# @param string $cmd Command given to generate items
113
# @param string $test (optional) Test title. Default is "$cmd<TAB> should show completions"
114
# @param string $prompt (optional) Bash prompt. Default is "/@"
115
# @param integer $size (optional) Chunk size. Default is 20.
116
# @param string $cword (optional) Last argument of $cmd which is an
117
# argument-to-complete and to be replaced with the longest common prefix
118
# of $expected. If empty string (default), `assert_complete' autodetects
119
# if the last argument is an argument-to-complete by checking if $cmd
120
# doesn't end with whitespace. Specifying `cword' should only be necessary
121
# if this autodetection fails, e.g. when the last whitespace is escaped or
122
# quoted, e.g. "finger foo\ " or "finger 'foo "
123
# @param list $filters (optional) List of filters to apply to this function to tweak
124
# the expected completions and argument-to-complete. Possible values:
125
# - "ltrim_colon_completions"
126
# @result boolean True if successful, False if not
127
proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""} {filters ""}} {
162
# @param string $test Test title
163
# @param list $args Options:
164
# -prompt PROMPT Bash prompt. Default is `/@'
165
# -chunk-size CHUNK-SIZE Compare list CHUNK-SIZE items at
166
# a time. Default is 20.
167
# -nospace Don't expect space character to be output after completion match.
168
# Valid only if a single completion is expected.
169
# -ltrim-colon-completions Left-trim completions with cword containing
171
# -expect-cmd-full Expect the full $cmd to be echoed. Expected is:
175
# $prompt + $cmd + longest-common-prefix-of-$expected
177
# -expect-cmd-minus DWORD Expect $cmd minus DWORD to be echoed.
182
# $prompt + ($cmd - DWORD) + longest-common-prefix-of-$expected
184
proc assert_complete {expected cmd {test ""} {args {}}} {
186
array set arg [::cmdline::getoptions args {
187
{prompt.arg "/@" "bash prompt"}
188
{chunk-size.arg 20 "compare N list items at a time"}
189
{nospace "don't expect space after completion"}
190
{ltrim-colon-completions "left-trim completions with cword containing :"}
191
{expect-cmd-full "Expect full cmd after prompt"}
192
{expect-cmd-minus.arg "" "Expect cmd minus DWORD after prompt"}
128
194
if {[llength $expected] == 0} {
129
195
assert_no_complete $cmd $test
131
if {$test == ""} {set test "$cmd should show completions"}
133
if {[llength $expected] == 1} {
136
if {[lsearch -exact $filters "ltrim_colon_completions"] == -1} {
137
set cur ""; # Default to empty word to complete on
138
set words [split_words_bash $cmd]
139
if {[llength $words] > 1} {
140
# Assume last word of `$cmd' is word to complete on.
141
set index [expr [llength $words] - 1]
142
set cur [lindex $words $index]
144
# Remove second word from beginning of single item $expected
145
if {[string first $cur $expected] == 0} {
146
set expected [list [string range $expected [string length $cur] end]]
150
expect -ex "$cmd\r\n"
151
# Make sure expected items are unique
152
set expected [lsort -unique $expected]
155
if {[lsearch -exact $filters "ltrim_colon_completions"] != -1} {
156
# If partial contains colon (:), remove partial from begin of items
157
# See also: bash_completion.__ltrim_colon_completions()
158
_ltrim_colon_completions cword expected
161
if {[match_items $expected $test $prompt $size]} {
162
if {[llength $expected] == 1} {
165
# Remove optional (partial) last argument-to-complete from `cmd',
166
# E.g. "finger test@" becomes "finger"
168
if {[lsearch -exact $filters "ltrim_colon_completions"] != -1} {
171
set cmd2 [_remove_cword_from_cmd $cmd $cword]
174
# Determine common prefix of completions
175
set common [::textutil::string::longestCommonPrefixList $expected]
176
#if {[string length $common] > 0} {set common " $common"}
178
-ex "$prompt$cmd2$common" { pass "$test" }
179
-re $prompt { unresolved "$test at prompt" }
180
-re eof { unresolved "eof" }
187
}; # assert_complete()
190
# @param string $cmd Command to remove cword from
191
# @param string $cword (optional) Last argument of $cmd which is an
192
# argument-to-complete and to be deleted. If empty string (default),
193
# `_remove_cword_from_cmd' autodetects if the last argument is an
194
# argument-to-complete by checking if $cmd doesn't end with whitespace.
195
# Specifying `cword' is only necessary if this autodetection fails, e.g.
196
} elseif {[llength $expected] == 1} {
197
eval assert_complete_one \$expected \$cmd \$test $args_orig
199
eval assert_complete_many \$expected \$cmd \$test $args_orig
204
# Make sure the expected multiple items are returned by TAB-completing the
206
# @see assert_complete()
207
proc assert_complete_many {expected cmd {test ""} {args {}}} {
208
array set arg [::cmdline::getoptions args {
209
{prompt.arg "/@" "bash prompt"}
210
{chunk-size.arg 20 "compare N list items at a time"}
211
{nospace "don't expect space after completion"}
212
{ltrim-colon-completions "left-trim completions with cword containing :"}
213
{expect-cmd-full "Expect full cmd after prompt"}
214
{expect-cmd-minus.arg "" "Expect cmd minus CWORD after prompt"}
216
if {$test == ""} {set test "$cmd should show completions"}
217
set prompt $arg(prompt)
219
if {$arg(expect-cmd-minus) != ""} {set dword $arg(expect-cmd-minus)}
222
expect -ex "$cmd\r\n"
224
# Make sure expected items are unique
225
set expected [lsort -unique $expected]
227
# Determine common prefix of completions
228
set common [::textutil::string::longestCommonPrefixList $expected]
230
if {$arg(ltrim-colon-completions)} {
231
# If partial contains colon (:), remove partial from begin of items
232
_ltrim_colon_completions $cmd expected dword
234
set cmd2 [_remove_cword_from_cmd $cmd $dword $common]
236
set prompt "$prompt$cmd2$common"
237
if {$arg(nospace)} {set endspace ""} else {set endspace "-end-space"}
238
set endprompt "-end-prompt"
240
eval match_items \$expected -bash-sort -chunk-size \
241
\$arg(chunk-size) $endprompt $endspace -prompt \$prompt
250
# Make sure the expected single item is returned by TAB-completing the
252
# @see assert_complete()
253
proc assert_complete_one {expected cmd {test ""} {args {}}} {
254
array set arg [::cmdline::getoptions args {
255
{prompt.arg "/@" "bash prompt"}
256
{chunk-size.arg 20 "compare N list items at a time"}
257
{nospace "don't expect space after completion"}
258
{ltrim-colon-completions "left-trim completions with cword containing :"}
259
{expect-cmd-full "Expect full cmd after prompt"}
260
{expect-cmd-minus.arg "" "Expect cmd minus CWORD after prompt"}
262
set prompt $arg(prompt)
264
if {$test == ""} {set test "$cmd should show completion"}
267
if {$arg(ltrim-colon-completions)} {
268
# If partial contains colon (:), remove partial from begin of items
269
_ltrim_colon_completions $cmd expected cword
271
set cur ""; # Default to empty word to complete on
272
set words [split_words_bash $cmd]
273
if {[llength $words] > 1} {
274
# Assume last word of `$cmd' is word to complete on.
275
set index [expr [llength $words] - 1]
276
set cur [lindex $words $index]
278
# Remove second word from beginning of $expected
279
if {[string first $cur $expected] == 0} {
280
set expected [list [string range $expected [string length $cur] end]]
284
if {$arg(nospace)} {set endspace ""} else {set endspace "-end-space"}
286
eval match_items \$expected -bash-sort -chunk-size \
287
\$arg(chunk-size) $endspace -prompt \$prompt
296
# @param string $cmd Command to remove current-word-to-complete from.
297
# @param string $dword (optional) Manually specify current-word-to-complete,
298
# i.e. word to remove from $cmd. If empty string (default),
299
# `_remove_cword_from_cmd' autodetects if the last argument is the
300
# current-word-to-complete by checking if $cmd doesn't end with whitespace.
301
# Specifying `dword' is only necessary if this autodetection fails, e.g.
196
302
# when the last whitespace is escaped or quoted, e.g. "finger foo\ " or
198
# @return string Command with cword removed
199
proc _remove_cword_from_cmd {cmd {cword ""}} {
304
# @param string $common (optional) Common prefix of expected completions.
305
# @return string Command with current-word-to-complete removed
306
proc _remove_cword_from_cmd {cmd {dword ""} {common ""}} {
201
# Is $cword specified?
202
if {[string length $cword] > 0} {
203
# Remove $cword from end of $cmd
204
if {[string last $cword $cmd] == [string length $cmd] - [string length $cword]} {
205
set cmd2 [string range $cmd 0 [expr [string last $cword $cmd] - 1]]
308
# Is $dword specified?
309
if {[string length $dword] > 0} {
310
# Remove $dword from end of $cmd
311
if {[string last $dword $cmd] == [string length $cmd] - [string length $dword]} {
312
set cmd2 [string range $cmd 0 [expr [string last $dword $cmd] - 1]]
208
# No, $cword not specified;
209
# Check if last argument is really an-argument-to-complete, i.e.
315
# No, $dword not specified;
316
# Check if last argument is really a word-to-complete, i.e.
210
317
# doesn't end with whitespace.
211
318
# NOTE: This check fails if trailing whitespace is escaped or quoted,
212
319
# e.g. "finger foo\ " or "finger 'foo ". Specify parameter
213
# $cword in those cases.
320
# $dword in those cases.
214
321
# Is last char whitespace?
215
322
if {! [string is space [string range $cmd end end]]} {
216
323
# No, last char isn't whitespace;
217
# Remove argument-to-complete from end of $cmd
218
set cmd2 [lrange [split $cmd] 0 end-1]
324
set cmds [split $cmd]
325
# Does word-to-complete start with $common?
326
if {[string first $common [lrange $cmds end end]] == 0} {
327
# Remove word-to-complete from end of $cmd
328
set cmd2 [lrange $cmds 0 end-1]
223
}; # _remove_cword_from_cmd()
226
337
# Escape regexp special characters