[Bash-completion-commits] [SCM] bash-completion branch, master, updated. 1061876bbc70f2e3d9c6d09fcd06796df2d59123

Freddy Vulto fvulto at gmail.com
Fri Jan 29 22:25:14 UTC 2010


The following commit has been merged in the master branch:
commit 1061876bbc70f2e3d9c6d09fcd06796df2d59123
Merge: e7d7ae81efc694e45d6667f6decc1afde407831d d866854066fb3b6711cf6fc92ff648a0a12ee9d8
Author: Freddy Vulto <fvulto at gmail.com>
Date:   Fri Jan 29 23:24:58 2010 +0100

    Merge branch 'fvu'

diff --combined CHANGES
index 69f4015,bb9f57d..106f997
--- a/CHANGES
+++ b/CHANGES
@@@ -67,6 -67,7 +67,7 @@@ bash-completion (2.x
    [ Leonard Crestez ]
    * Improve ssh -o suboption completion (Alioth: #312122).
    * Fix NFS mounts completion (Alioth: #312285).
+   * Fix completion of usernames (Alioth: #311396, Debian: #511788).
  
    [ Raphaël Droz ]
    * Add xsltproc completion (Alioth: #311843).
@@@ -74,9 -75,6 +75,9 @@@
    [ Adrian Friedli ]
    * Add ipv6calc completion.
  
 +  [ Ildar Mulyukov ]
 +  * Add showmount completion (Alioth: #312285).
 +
   -- David Paleino <d.paleino at gmail.com>  Sun, 11 Oct 2009 11:11:57 +0200
  
  bash-completion (1.1)
diff --combined bash_completion
index b6709bd,57284a4..d59ef6f
--- a/bash_completion
+++ b/bash_completion
@@@ -771,20 -771,38 +771,38 @@@ _installed_modules(
          awk '{if (NR != 1) print $1}' )" -- "$1" ) )
  }
  
- # This function completes on user:group format
+ # This function completes on user or user:group format; as for chown and cpio.
  #
+ # The : must be added manually; it will only complete usernames initially.
+ # The legacy user.group format is not supported.
+ #
+ # It assumes compopt -o filenames; but doesn't touch it.
  _usergroup()
  {
      local IFS=$'\n'
-     cur=${cur//\\\\ / }
-     if [[ $cur = *@(\\:|.)* ]]; then
-         user=${cur%%*([^:.])}
-         COMPREPLY=( $(compgen -P ${user/\\\\} -g -- ${cur##*[.:]}) )
+     if [[ $cur = *\\\\* || $cur = *:*:* ]]; then
+         # Give up early on if something seems horribly wrong.
+         return
+     elif [[ $cur = *\\:* ]]; then
+         # Completing group after 'user\:gr<TAB>'.
+         # Reply with a list of groups prefixed with 'user:', readline will
+         # escape to the colon.
+         local prefix
+         prefix=${cur%%*([^:])}
+         prefix=${prefix//\\}
+         COMPREPLY=( $( compgen -P "$prefix" -g -- "${cur#*[:]}" ) )
      elif [[ $cur = *:* ]]; then
-         COMPREPLY=( $( compgen -g -- ${cur##*[.:]} ) )
+         # Completing group after 'user:gr<TAB>'.
+         # Reply with a list of unprefixed groups since readline with split on :
+         # and only replace the 'gr' part
+         COMPREPLY=( $( compgen -g -- "${cur#*:}" ) )
      else
-         type compopt &>/dev/null && compopt -o nospace
-         COMPREPLY=( $( compgen -S : -u -- "$cur" ) )
+         # Completing a partial 'usernam<TAB>'.
+         #
+         # Don't suffix with a : because readline will escape it and add a
+         # slash. It's better to complete into 'chown username ' than 'chown
+         # username\:'.
+         COMPREPLY=( $( compgen -u -- "$cur" ) )
      fi
  }
  
@@@ -908,8 -926,10 +926,10 @@@ complete -F _service servic
  _chown()
  {
      local cur prev split=false
-     cur=`_get_cword`
-     prev=${COMP_WORDS[COMP_CWORD-1]}
+ 
+     # Get cur and prev words; but don't treat user:group as separate words.
+     cur=`_get_cword :`
+     prev=`_get_pword :`
  
      _split_longopt && split=true
  
@@@ -926,22 -946,22 +946,22 @@@
  
      $split && return 0
  
-     # options completion
      if [[ "$cur" == -* ]]; then
+         # Complete -options
          COMPREPLY=( $( compgen -W '-c -h -f -R -v --changes --dereference \
              --no-dereference --from --silent --quiet --reference --recursive \
              --verbose --help --version' -- "$cur" ) )
      else
-         _count_args
- 
-         case $args in
-             1)
-                 _usergroup
-                 ;;
-             *)
-                 _filedir
-                 ;;
-         esac
+         local args
+ 
+         # The first argument is an usergroup; the rest are filedir.
+         _count_args :
+ 
+         if [[ $args == 1 ]]; then
+             _usergroup
+         else
+             _filedir
+         fi
      fi
  } # _chown()
  complete -F _chown -o filenames chown
@@@ -1402,7 -1422,7 +1422,7 @@@ _known_hosts_real(
  } # _known_hosts_real()
  complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 ping \
      ping6 fping fping6 telnet host nslookup rsh rlogin ftp dig mtr \
 -    ssh-installkeys
 +    ssh-installkeys showmount
  
  # This meta-cd function observes the CDPATH variable, so that cd additionally
  # completes on directories under those specified in CDPATH.
diff --combined test/lib/library.exp
index f9895d8,6b56e49..fab33bf
--- a/test/lib/library.exp
+++ b/test/lib/library.exp
@@@ -104,7 -104,7 +104,7 @@@ proc assert_bash_list_dir {expected cm
  
  # Make sure the expected items are returned by TAB-completing the specified
  # command.
- # @param list $expected
+ # @param list $expected  Expected completions.
  # @param string $cmd  Command given to generate items
  # @param string $test  (optional) Test title.  Default is "$cmd<TAB> should show completions"
  # @param string $prompt  (optional) Bash prompt.  Default is "/@"
@@@ -113,66 -113,72 +113,72 @@@
  #     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' is only necessary if
- #     this autodetection fails, e.g.  when the last whitespace is escaped or
+ #     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"
  # @result boolean  True if successful, False if not
  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"
-         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
+     if {[llength $expected] == 0} {
+         assert_no_complete $cmd $test
      } else {
-         expect -ex "$cmd\r\n"
-         # Make sure expected items are unique
-         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 $prompt $size]} {
+         if {$test == ""} {set test "$cmd should show completions"}
+         send "$cmd\t"
          if {[llength $expected] == 1} {
-             pass "$test"
+             expect -ex "$cmd"
+ 
+             if {[lsearch -exact $filters "ltrim_colon_completions"] == -1} {
+                 set cur "";  # Default to empty word to complete on
+                 set words [split_words_bash $cmd]
+                 if {[llength $words] > 1} {
+                         # Assume last word of `$cmd' is word to complete on.
+                     set index [expr [llength $words] - 1]
+                     set cur [lindex $words $index]
+                 }; # if
+                     # Remove second word from beginning of single item $expected
+                 if {[string first $cur $expected] == 0} {
+                     set expected [list [string range $expected [string length $cur] end]]
+                 }; # if
+             }; # if
          } else {
-             # Remove optional (partial) last argument-to-complete from `cmd',
-             # E.g. "finger test@" becomes "finger"
+             expect -ex "$cmd\r\n"
+             # Make sure expected items are unique
+             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 {[lsearch -exact $filters "ltrim_colon_completions"] != -1} {
-                 set cmd2 $cmd
+         if {[match_items $expected $test $prompt $size]} {
+             if {[llength $expected] == 1} {
+                 pass "$test"
              } else {
-                 set cmd2 [_remove_cword_from_cmd $cmd $cword]
+                 # Remove optional (partial) last argument-to-complete from `cmd',
+                 # E.g. "finger test@" becomes "finger"
+ 
+                 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"}
+                 expect {
+                     -ex "$prompt$cmd2$common" { pass "$test" }
+                     -re $prompt { unresolved "$test at prompt" }
+                     -re eof { unresolved "eof" }
+                 }; # expect
              }; # if
- 
-             # Determine common prefix of completions
-             set common [::textutil::string::longestCommonPrefixList $expected]
-             #if {[string length $common] > 0} {set common " $common"}
-             expect {
-                 -ex "$prompt$cmd2$common" { pass "$test" }
-                 -re $prompt { unresolved "$test at prompt" }
-                 -re eof { unresolved "eof" }
-             }; # expect
+         } else {
+             fail "$test"
          }; # if
-     } else {
-         fail "$test"
      }; # if
  }; # assert_complete()
  
@@@ -213,13 -219,18 +219,18 @@@ proc _remove_cword_from_cmd {cmd {cwor
  }; # _remove_cword_from_cmd()
  
  
+ # Escape regexp special characters
+ proc _escape_regexp_chars {var} {
+     upvar $var str
+     regsub -all {([\^$+*?.|(){}[\]\\])} $str {\\\1} str
+ }
+ 
  # Make sure any completions are returned
  proc assert_complete_any {cmd {test ""} {prompt /@}} {
      if {$test == ""} {set test "$cmd should show completions"}
      send "$cmd\t"
      expect -ex "$cmd"
-         # Escape special regexp characters
-     regsub -all {([\^$+*?.|(){}[\]\\])} $cmd {\\\1} cmd
+     _escape_regexp_chars cmd
      expect {
          -timeout 1
          # Match completions, multiple words
@@@ -415,6 -426,29 +426,29 @@@ proc assert_exec {cmd {stdout ''} {tes
  }; # assert_exec()
  
  
+ # Check that no completion is attempted on a certain command.
+ # Params:
+ # @cmd The command to attempt to complete.
+ # @test Optional parameter with test name.
+ proc assert_no_complete {{cmd} {test ""}} {
+     if {[string length $test] == 0} {
+         set test "$cmd shouldn't complete"
+     }; # if
+ 
+     send "$cmd\t"
+     expect -ex "$cmd"
+ 
+     # We can't anchor on $, simulate typing a magical string instead.
+     set endguard "Magic End Guard"
+     send "$endguard"
+     expect {
+         -re "^$endguard$" { pass "$test" }
+         default { fail "$test" }
+         timeout { fail "$test" }
+     }; # expect
+ }; # assert_no_complete()
+ 
+ 
  # Sort list.
  # `exec sort' is used instead of `lsort' to achieve exactly the
  #  same sort order as in bash.
@@@ -515,8 -549,7 +549,7 @@@ proc match_items {items test {prompt /@
          if {$i > $size} { set expected "\\s*" } else { set expected "" }
          for {set j 0} {$j < $size && $i + $j < [llength $items]} {incr j} {
              set item "[lindex $items [expr {$i + $j}]]"
-                 # Escape special regexp characters
-             regsub -all {([\^$+*?.|(){}[\]\\])} $item {\\\1} item
+             _escape_regexp_chars item
              append expected $item
              if {[llength $items] > 1} {append expected {\s+}};
          }; # for
@@@ -596,8 -629,8 +629,8 @@@ proc save_env {{file ""}} 
  # @param string  File to save the environment to.  Default is "$TESTDIR/tmp/env1~".
  # @see assert_env_unmodified()
  proc _save_env {{file ""}} {
 -    assert_bash_exec "{ set; declare -F; } > $file"
 -}; # save_env()
 +    assert_bash_exec "{ set; declare -F; shopt -p; } > $file"
 +}; # _save_env()
  
  
  # Source bash_completion package
@@@ -609,6 -642,46 +642,46 @@@ proc source_bash_completion {} 
  }; # source_bash_completion()
  
  
+ # Split line into words, disregarding backslash escapes (e.g. \b (backspace),
+ # \g (bell)), but taking backslashed spaces into account.
+ # Aimed for simulating bash word splitting.
+ # Example usage:
+ #
+ #     % set a {f cd\ \be}
+ #     % split_words $a
+ #     f {cd\ \be}
+ #
+ # @param string  Line to split
+ # @return list  Words
+ proc split_words_bash {line} {
+     set words {}
+     set glue false
+     foreach part [split $line] {
+         set glue_next false
+         # Does `part' end with a backslash (\)?
+         if {[string last "\\" $part] == [string length $part] - [string length "\\"]} {
+             # Remove end backslash
+             set part [string range $part 0 [expr [string length $part] - [string length "\\"] - 1]]
+             # Indicate glue on next run
+             set glue_next true
+         }; # if
+         # Must `part' be appended to latest word (= glue)?
+         if {[llength $words] > 0 && [string is true $glue]} {
+             # Yes, join `part' to latest word;
+             set zz [lindex $words [expr [llength $words] - 1]]
+             # Separate glue with backslash-space (\ );
+             lset words [expr [llength $words] - 1] "$zz\\ $part"
+         } else {
+             # No, don't append word to latest word;
+             # Append `part' as separate word
+             lappend words $part
+         }; # if
+         set glue $glue_next
+     }; # foreach
+     return $words
+ }; # split_words_bash()
+ 
+ 
  # 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