about summary refs log tree commit diff
path: root/Completion
diff options
context:
space:
mode:
Diffstat (limited to 'Completion')
-rw-r--r--Completion/Unix/Command/_subversion69
1 files changed, 43 insertions, 26 deletions
diff --git a/Completion/Unix/Command/_subversion b/Completion/Unix/Command/_subversion
index 9ef3077f6..cb5cbd374 100644
--- a/Completion/Unix/Command/_subversion
+++ b/Completion/Unix/Command/_subversion
@@ -68,7 +68,6 @@ _svn () {
     ;;
     args)
       local cmd args usage idx
-      typeset -gHA _cache_svn_status _cache_svn_mtime
 
       cmd="${${(k)_svn_cmds[(R)*:$words[1]:*]}:-${(k)_svn_cmds[(i):$words[1]:]}}"
       if (( $#cmd )); then
@@ -141,7 +140,7 @@ _svn () {
           (commit)
             args=(
 	      ${args/(#b)(*--file*):arg:/$match[1]:file:_files}
-              '*:file:_files -g "*(e:_svn_status:)"'
+              '*:file: _svn_modified "committable"'
             )
           ;;
           (delete)
@@ -151,7 +150,7 @@ _svn () {
           ;;
           (diff)
             args+=(
-	      '*: : _alternative "files:file:_files -g \*\(e:_svn_status:\)" "urls:URL:_svn_urls"'
+	      '*: : _alternative "files:file: _svn_modified revertable" "urls:URL:_svn_urls"'
 	    )
           ;;
           (help)
@@ -201,7 +200,7 @@ _svn () {
           ;;
           (revert)
             args+=(
-              '*:file:_files -g "(.svn|*)(/e:_svn_deletedfiles:,e:_svn_status:)"'
+              '*:file: _svn_modified "revertable"'
             )
           ;;
           (x-unshelve)
@@ -368,33 +367,51 @@ _svn_conflicts() {
   () { (( $# > 0 )) } $REPLY.(mine|r<->)(NY1)
 }
 
-(( $+functions[_svn_deletedfiles] )) ||
-_svn_deletedfiles() {
-  # Typical usage would be _files -g '.svn(/e:_svn_deletedfiles:)'
-  local cont controlled
-  reply=( )
-  [[ $REPLY = (*/|).svn ]] || return
-  controlled=( $REPLY/text-base/*.svn-base(N:r:t) )
-  for cont in ${controlled}; do
-    [[ -e $REPLY:h/$cont ]] || reply+=( ${REPLY%.svn}$cont )
-  done
-}
+(( $+functions[_svn_modified] )) ||
+_svn_modified() {
+  setopt localoptions extendedglob
 
-(( $+functions[_svn_status] )) ||
-_svn_status() {
-  local dir=$REPLY:h
-  local pat="${1:-([ADMR~]|?M)}"
+  local depth dir expl partial_word space=' '
 
-  zmodload -F zsh/stat b:zstat 2>/dev/null
-  local key="$(zstat +device $dir):$(zstat +inode $dir)"
-  local mtime="$(zstat +mtime $dir/.svn/entries)"
+  local svn_context=$1
 
-  if (( ! $+_cache_svn_status[$key] || _cache_svn_mtime[$key] != mtime )); then
-    _cache_svn_status[$key]="$(_call_program files svn status -q -N -- $dir)"
-    _cache_svn_mtime[$key]="$mtime"
+  local partial_word=${(Q)words[CURRENT]}
+  if [[ -z $partial_word ]]; then
+    dir="./"
+  elif [[ -d $partial_word ]]; then
+    dir=$partial_word
+  else
+    dir=${partial_word:h}
   fi
 
-  (( ${(M)#${(f)_cache_svn_status[$key]}:#(#s)${~pat}*$REPLY} ))
+  if zstyle -T ":completion:${curcontext}:${curtag}" verbose; then
+    depth=infinity
+  else
+    depth=immediates
+  fi
+
+  local -a status_lines
+  # Run 'status'
+  status_lines=( ${(f)"$(_call_program modified-files "svn status -q --depth=${(q)depth} -- ${(q)dir}")"} )
+  # Filter to only the right set of statuses
+  case $svn_context in
+    (committable)
+      status_lines=( ${(M)status_lines:#(#s)([ADMR]?|?M)${space}???${space}${space}*} )
+      ;;
+    (revertable)
+      status_lines=( ${(M)status_lines:#(#s)([ACDMR~!]?|?[CM])${space}????${space}*} )
+      ;;
+  esac
+  # Strip the 7 status-letter columns and the column of spaces
+  status_lines=( ${status_lines#????????} )
+  # Strip one leading space.  This is in case `svn status` ever adds another
+  # column.  If that hasn't happened and you're reading this comment because
+  # the following line broke your use of filenames that start with a literal
+  # space, well, nice to meet you!  I didn't know you existed.
+  status_lines=( ${status_lines#${space}} )
+
+  _wanted svn-modified expl 'modified files in svn' \
+    compadd - "${status_lines[@]}"
 }
 
 (( $+functions[_svn_remote_paths] )) ||