[Bash-completion-commits] [SCM] bash-completion branch, master, updated. c72e20b42fe113b5496c3424598dbc5e41e1e644
Crestez Dan Leonard
cdleonard at gmail.com
Sat Feb 6 23:11:19 UTC 2010
The following commit has been merged in the master branch:
commit c72e20b42fe113b5496c3424598dbc5e41e1e644
Merge: 6810e5564528398ec5bde31e7db4a9cdd4791917 dc18aae4e4159c509a4a94d7495ee01cd350d4d0
Author: Crestez Dan Leonard <cdleonard at gmail.com>
Date: Sun Feb 7 01:09:17 2010 +0200
Merge branch 'find-unique-completion-pair'
diff --combined test/lib/completions/chown.exp
index 3312f5b,b1207ee..953b2b0
--- a/test/lib/completions/chown.exp
+++ b/test/lib/completions/chown.exp
@@@ -10,33 -10,25 +10,28 @@@ proc teardown {}
setup
-assert_complete_any "chown "
+set users [exec bash -c "compgen -A user"]
+assert_complete $users "chown "
+
+
sync_after_int
- # All the tests use the root:root user and group. They're assumed to exist.
- set fulluser "root"
- set fullgroup "root"
-
- # Partial username is assumed to be unambiguous.
- set partuser "roo"
- set partgroup "roo"
-
- # Skip tests if root:root not available or if roo:roo matches multiple
- # users/groups
- #
- # compgen -A is used because it's a bash builtin and available everywhere.
- # The || true part prevents exec from throwing an exception if nothing is
- # found.
- if {[exec bash -c "compgen -A user $partuser || true" | wc -l] > 1 ||
- [exec bash -c "compgen -A user $fulluser || true" | wc -l] != 1 ||
- [exec bash -c "compgen -A group $partgroup || true" | wc -l] > 1 ||
- [exec bash -c "compgen -A group $fullgroup || true" | wc -l] != 1} {
- untested "Not running complex chown tests."
- } else {
+ # Find user/group suitable for testing.
+ set failed_find_unique_completion 0
+ foreach ug {user group} {
+ # compgen -A is used because it's a bash builtin and available everywhere.
+ # The || true part prevents exec from throwing an exception if nothing is
+ # found (very very unlikely).
+ set list [split [exec bash -c "compgen -A $ug || true"] "\n"]
+ if {![find_unique_completion_pair $list part$ug full$ug]} {
+ untested "Not running complex chown tests; no suitable test $ug found."
+ set failed_find_unique_completion 1
+ }
+ }
+
+ # These tests require an unique completion.
+ if {!$failed_find_unique_completion} {
assert_complete $fulluser "chown $partuser"
sync_after_int
diff --combined test/lib/library.exp
index 387b40b,4594900..3de310b
--- a/test/lib/library.exp
+++ b/test/lib/library.exp
@@@ -451,23 -451,6 +451,23 @@@ proc assert_no_complete {{cmd} {test ""
}; # assert_no_complete()
+# Source/run file with additional tests if completion for the specified command
+# is installed in bash.
+# @param string $command Command to check completion availability for.
+# @param string $file (optional) File to source/run. Default is
+# "lib/completions/$cmd.exp".
+proc assert_source_completions {command {file ""}} {
+ if {[is_bash_completion_installed_for $command]} {
+ if {[string length $file] == 0} {
+ set file "lib/completions/$command.exp"
+ }
+ source $file
+ } else {
+ untested $command
+ }
+}; # assert_source_completions()
+
+
# Sort list.
# `exec sort' is used instead of `lsort' to achieve exactly the
# same sort order as in bash.
@@@ -479,12 -462,10 +479,12 @@@ proc bash_sort {items}
# Get 'known' hostnames. Looks also in ssh's 'known_hosts' files.
+# @param string cword (optional) Word, hosts should start with.
# @return list Hostnames
# @see get_hosts()
-proc get_known_hosts {} {
- assert_bash_exec {_known_hosts_real ''; echo_array COMPREPLY} {} /@ result
+proc get_known_hosts {{cword ''}} {
+ assert_bash_exec "_known_hosts_real '$cword'; echo_array COMPREPLY" \
+ {} /@ result
return $result
}; # get_known_hosts()
@@@ -551,24 -532,6 +551,24 @@@ proc init_tcl_bash_globals {}
}; # init_tcl_bash_globals()
+# Check whether completion is installed for the specified command by executing
+# `complete -p ...' in bash.
+# @param string $command Command to check completion availability for.
+# @return boolean True (1) if completion is installed, False (0) if not.
+proc is_bash_completion_installed_for {command} {
+ set test "$command should have completion installed in bash"
+ set cmd "complete -p $command &> /dev/null && echo -n 0 || echo -n 1"
+ send "$cmd\r"
+ expect "$cmd\r\n"
+ expect {
+ -ex 0 { set result true }
+ -ex 1 { set result false }
+ }
+ expect "/@"
+ return $result
+}; # is_bash_completion_installed_for()
+
+
# Detect if test suite is running under Cygwin/Windows
proc is_cygwin {} {
expr {[string first [string tolower [exec uname -s]] cygwin] >= 0}
@@@ -721,6 -684,73 +721,73 @@@ proc split_words_bash {line}
}; # split_words_bash()
+ # Given a list of items this proc finds a (part, full) pair so that when
+ # completing from $part $full will be the only option.
+ #
+ # Arguments:
+ # list The list of full completions.
+ # partName Output parameter for the partial string.
+ # fullName Output parameter for the full string, member of item.
+ #
+ # Results:
+ # 1, or 0 if no suitable result was found.
+ proc find_unique_completion_pair {{list} {partName} {fullName}} {
+ upvar $partName part
+ upvar $fullName full
+ set bestscore 0
+ set list [lsort $list]
+ set n [llength $list]
+ for {set i 0} {$i < $n} {incr i} {
+ set cur [lindex $list $i]
+ set curlen [string length $cur]
+
+ set prev [lindex $list [expr {$i - 1}]]
+ set next [lindex $list [expr {$i + 1}]]
+ set diffprev [expr {$prev == ""}]
+ set diffnext [expr {$next == ""}]
+
+ # Analyse each item of the list and look for the minimum length of the
+ # partial prefix which is distinct from both $next and $prev. The list
+ # is sorted so the prefix will be unique in the entire list.
+ #
+ # In the worst case we analyse every character in the list 3 times.
+ # That's actually very fast, sorting could take more.
+ for {set j 0} {$j < $curlen} {incr j} {
+ set curchar [string index $cur $j]
+ if {!$diffprev && [string index $prev $j] != $curchar} {
+ set diffprev 1
+ }
+ if {!$diffnext && [string index $next $j] != $curchar} {
+ set diffnext 1
+ }
+ if {$diffnext && $diffprev} {
+ break
+ }
+ }
+
+ # At the end of the loop $j is the index of last character of
+ # the unique partial prefix. The length is one plus that.
+ set parlen [expr {$j + 1}]
+ if {$parlen >= $curlen} {
+ continue
+ }
+
+ # Try to find the most "readable pair"; look for a long pair where
+ # $part is about half of $full.
+ if {$parlen < $curlen / 2} {
+ set parlen [expr {$curlen / 2}]
+ }
+ set score [expr {$curlen - $parlen}]
+ if {$score > $bestscore} {
+ set bestscore $score
+ set part [string range $cur 0 [expr {$parlen - 1}]]
+ set full $cur
+ }
+ }
+ return [expr {$bestscore != 0}]
+ }
+
+
# Start bash running as test environment.
proc start_bash {} {
global TESTDIR TOOL_EXECUTABLE spawn_id
--
bash-completion
More information about the Bash-completion-commits
mailing list