[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