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

Re: _canonical_path not working on *BSD



On Thu, 27 Mar 2008 12:08:07 +0100
Pea <zsh@xxxxxxxxxxxx> wrote:
> [pea@pea-dsktp:~]% umount _canonical_paths_get_canonical_path:unfunction:1: no such hash table element: chpwd
> _canonical_paths_get_canonical_path:unfunction:1: no such hash table element: chpwd

I thought unfunction was silent if a function didn't exist, as is now
true of (and required for) unset, but apparently not.

Since I can't seem to get away from this, I've rewritten the function
more canonically so that the helper functions only get loaded once
and aren't buried in the body of the main function that gets stored.
Most of the patch is consequent rearrangement.

Index: Completion/Unix/Type/_canonical_paths
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Type/_canonical_paths,v
retrieving revision 1.3
diff -u -r1.3 _canonical_paths
--- Completion/Unix/Type/_canonical_paths	27 Mar 2008 10:35:21 -0000	1.3
+++ Completion/Unix/Type/_canonical_paths	27 Mar 2008 11:20:34 -0000
@@ -13,27 +13,13 @@
 # case they are already so. `tag' and `desc' arguments are well, obvious :) In
 # addition, the options -M, -J, -V, -1, -2, -n, -F, -X are passed to compadd.
 
-local __index
-typeset -a __gopts __opts
-
-zparseopts -D -a __gopts M: J: V: 1 2 n F: X: A:=__opts N=__opts
-
-: ${1:=canonical-paths} ${2:=path}
-
-__index=$__opts[(I)-A]
-(( $__index )) && set -- $@ ${(P)__opts[__index+1]}
-
-local expl ret=1 tag=$1 desc=$2
-
-shift 2
-
-if ! zmodload -F zsh/stat b:zstat 2>/dev/null; then
-  _wanted "$tag" expl "$desc" compadd $__gopts $@ && ret=0
-  return ret
-fi
-
-typeset REPLY
-typeset -a matches files
+_canonical_paths_pwd() {
+  # Get the canonical directory name by changing to it.
+  # To be run in a subshell.
+  (( ${+functions[chpwd]} )) && unfunction chpwd
+  setopt CHASE_LINKS
+  cd $1 2>/dev/null && pwd
+}
 
 _canonical_paths_get_canonical_path() {
   typeset newfile dir
@@ -55,34 +41,20 @@
   # Canonicalise the directory path.  We may not be able to
   # do this if we can't read all components.
   if [[ -d $REPLY ]]; then
-    dir="$(unfunction chpwd
-           setopt CHASE_LINKS
-           cd $REPLY 2>/dev/null && pwd)"
+    dir="$(_canonical_paths_pwd $REPLY)"
     if [[ -n $dir ]]; then
       REPLY=$dir
     fi
   elif [[ $REPLY = */*[^/] && $REPLY != /[^/]# ]]; then
     # Don't try this if there's a trailing slash or we're in
     # the root directory.
-    dir="$(unfunction chpwd
-           setopt CHASE_LINKS
-           cd ${REPLY%/*} 2>/dev/null && pwd)"
+    dir="$(_canonical_paths_pwd ${REPLY%/*})"
     if [[ -n $dir ]]; then
       REPLY=$dir/${REPLY##*/}
     fi
   fi
 }
 
-
-if (( $__opts[(I)-N] )); then
-  files=($@)
-else
-  for __index in $@; do
-    _canonical_paths_get_canonical_path $__index
-    files+=($REPLY)
-  done
-fi
-
 _canonical_paths_add_paths () {
   local origpref=$1 expref rltrim curpref canpref subdir
   [[ $2 != add ]] && matches=()
@@ -104,35 +76,70 @@
   done
 }
 
-local base=$PREFIX
-typeset -i blimit
+_canonical_paths() {
+  local __index
+  typeset -a __gopts __opts
+
+  zparseopts -D -a __gopts M: J: V: 1 2 n F: X: A:=__opts N=__opts
+
+  : ${1:=canonical-paths} ${2:=path}
+
+  __index=$__opts[(I)-A]
+  (( $__index )) && set -- $@ ${(P)__opts[__index+1]}
 
-_canonical_paths_add_paths $base
+  local expl ret=1 tag=$1 desc=$2
 
-if [[ -z $base ]]; then
-  _canonical_paths_add_paths / add
-elif [[ $base == ..(/.(|.))#(|/) ]]; then
-
-  # This style controls how many parent directory links (..) to chase searching
-  # for possible completions. The default is 8. Note that this chasing is
-  # triggered only when the user enters atleast a .. and the path completed
-  # contains only . or .. components. A value of 0 turns off .. link chasing
-  # altogether.
-
-  zstyle -s ":completion:${curcontext}:$tag" \
-    canonical-paths-back-limit blimit || blimit=8
-
-  if [[ $base != */ ]]; then
-    [[ $base != *.. ]] && base+=.
-    base+=/
+  shift 2
+
+  if ! zmodload -F zsh/stat b:zstat 2>/dev/null; then
+    _wanted "$tag" expl "$desc" compadd $__gopts $@ && ret=0
+    return ret
   fi
-  until [[ $base.. -ef $base || blimit -le 0 ]]; do
-    base+=../
-    _canonical_paths_add_paths $base add
-    blimit+=-1
-  done
-fi
 
-_wanted "$tag" expl "$desc" compadd $__gopts -Q -U -a matches && ret=0
+  typeset REPLY
+  typeset -a matches files
+
+  if (( $__opts[(I)-N] )); then
+    files=($@)
+  else
+    for __index in $@; do
+      _canonical_paths_get_canonical_path $__index
+      files+=($REPLY)
+    done
+  fi
+
+  local base=$PREFIX
+  typeset -i blimit
+
+  _canonical_paths_add_paths $base
+
+  if [[ -z $base ]]; then
+    _canonical_paths_add_paths / add
+  elif [[ $base == ..(/.(|.))#(|/) ]]; then
+
+    # This style controls how many parent directory links (..) to chase searching
+    # for possible completions. The default is 8. Note that this chasing is
+    # triggered only when the user enters atleast a .. and the path completed
+    # contains only . or .. components. A value of 0 turns off .. link chasing
+    # altogether.
+
+    zstyle -s ":completion:${curcontext}:$tag" \
+      canonical-paths-back-limit blimit || blimit=8
+
+    if [[ $base != */ ]]; then
+      [[ $base != *.. ]] && base+=.
+      base+=/
+    fi
+    until [[ $base.. -ef $base || blimit -le 0 ]]; do
+      base+=../
+      _canonical_paths_add_paths $base add
+      blimit+=-1
+    done
+  fi
+
+  _wanted "$tag" expl "$desc" compadd $__gopts -Q -U -a matches && ret=0
+
+  return ret
+}
 
-return ret
+_canonical_paths "$@"

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070



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