Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: Fix _file_descriptors



I noticed file descriptor completion didn't work, with the verbose style set
because when this is run,
  fds=( /dev/fd/<0-9>(N:t) )
the /dev/fd dir is open while the glob is performed, which results in
a spurious entry in the result, which then cannot be dereferenced. The
result is that the list array is not aligned to the fds array (and also
an error message is output), and an fd that doesn't exist is completed.

If the verbose style is not set, the spurious fd is not filtered.

---
 Completion/Zsh/Type/_file_descriptors |   34 ++++++++++++++++++--------------
 1 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/Completion/Zsh/Type/_file_descriptors b/Completion/Zsh/Type/_file_descriptors
index 3e251b7..38e2bf5 100644
--- a/Completion/Zsh/Type/_file_descriptors
+++ b/Completion/Zsh/Type/_file_descriptors
@@ -1,31 +1,35 @@
 #autoload
 
-local i fds expl list link sep
+local i expl link sep cmd
+local -a fds list
 
-fds=( /dev/fd/<0-9>(N:t) )
-
-if zstyle -T ":completion:${curcontext}:" verbose && [[ -h /proc/$$/fd/$fds[1] ]]; then
+if zstyle -T ":completion:${curcontext}:" verbose && [ -h /proc/$$/fd/<->([1]) ]; then
   zstyle -s ":completion:${curcontext}:" list-separator sep || sep=--
 
   if zmodload -F zsh/stat b:zstat; then
-    for i in "${fds[@]}"; do
-      zstat +link -A link /proc/$$/fd/$i
-      list+=( "$i $sep ${link[1]}" )
-    done
+    cmd='zstat +link -A link $REPLY; link=$link[1]'
   elif (( $+commands[readlink] )); then
-    for i in "${fds[@]}"; do
-      list+=( "$i $sep $(readlink /proc/$$/fd/$i)" )
-    done
+    cmd='link=$(readlink $REPLY)'
   else
-    for i in "${fds[@]}"; do
-      list+=( "$i $sep $(ls -l /proc/$$/fd/$i|sed 's/.*-> //' )" )
-    done
+    cmd='link=$(ls -l $REPLY|sed "s/.*-> //" )'
   fi
 
-  if (( $list[(I)* $sep ?*] )); then
+  # Filter out the fd for the dir opened during the glob (/proc/$$/fd)
+  : /proc/$$/fd/<->(e,$cmd'
+                       if [[ $link == /proc/$$/fd ]]; then
+                         false
+                       else
+                         fds+=( $REPLY:t )
+                         list+=( "$REPLY:t $sep $link" )
+                       fi
+                      ',)
+
+  if (( $list[(I)<-> $sep ?*] )); then
     _wanted file-descriptors expl 'file descriptor' compadd "$@" -d list -a - fds
     return
   fi
+else
+  fds=( /dev/fd/<->(N:t) )
 fi
 
 _wanted file-descriptors expl 'file descriptor' compadd -a "$@" - fds
-- 
1.7.5.4



Messages sorted by: Reverse Date, Date, Thread, Author