Package: zsh
Version: 4.3.2-8
Severity: wishlist
Tags: patch

Hi!

A major trouble for me in umount completion has been that
mountpoints completed are only the absolute paths given in mtab,
when actually I could enter relative paths, and for that matter any
path which canonicalizes to one of the absolute paths specified.
Couldn't find any function which did this in zsh. So, I decided to
write my own. This function takes a list of paths and completes
them, allowing the user to also enter other paths which are
equivalent to any of the paths provided. I have provided the
function/style documentation with the source. Here's the function:

#autoload

# This completion function completes all paths given to it, and also tries to
# offer completions which point to the same file as one of the paths given
# (relative path when an absolute path is given, and vice versa; when ..'s are
# present in the word to be completed, and some paths got from symlinks.

# Usage: _canonical_paths [-A var] [-N] [-MJV12nfX] tag desc paths...

# -A, if specified, takes the paths from the array variable specified. Paths can
# also be specified on the command line as shown above. -N, if specified,
# prevents canonicalizing the paths given before using them for completion, in
# 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 (( ! $+commands[readlink] )); then
  _wanted "$tag" expl "$desc" compadd $__gopts $@ && ret=0
  return ret
fi

typeset -a matches files

if (( $__opts[(I)-N] )); then
  files=($@)
else
  for __index in $@; do
    files+=$(readlink -qf $__index)
  done
fi

_canonical_paths_add_paths () {
  local origpref=$1 expref rltrim curpref canpref subdir
  [[ $2 != add ]] && matches=()
  expref=${~origpref}
  [[ $origpref == (|*/). ]] && rltrim=.
  curpref=${${expref%$rltrim}:-./}
  canpref=$(readlink -qf $curpref)
  if [[ $? -eq 0 ]]; then
    [[ $curpref == */ && $canpref == *[^/] ]] && canpref+=/
    canpref+=$rltrim
    [[ $expref == *[^/] && $canpref == */ ]] && origpref+=/
    matches+=(${${(M)files:#$canpref*}/$canpref/$origpref})
  fi
  for subdir in $expref?*(@); do
    _canonical_paths_add_paths ${subdir/$expref/$origpref} add
  done
}

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
Well, here's the patch to _mount which uses the above function. This
patch also fixes a bug which altogether prevented option completion!
(Do check if my fix is right, I am unable to understand why the
check for _fs_any is being made in the first place, when all the
_fs_* variables are local, and you can't optimize by initializing
them only once per session). I also updated the linux section with
whatever options that have come up since the last update. Also
removed a few linux options which were of no use in the command
line. Enough of the rant! Here's the patch:

43c43
< local args deffs=iso9660 tmp typeops=-t _fs_any _nfs_access _fs_nfs _nfs_ufs \
---
> local args deffs=iso9660 tmp typeops=-t _nfs_access _fs_nfs _nfs_ufs \
52a53,54
>   local _fs_any
> 
98c100
<     '(nosuid)suid[use suid and sgib bits]'
---
>     '(nosuid)suid[use suid and sgid bits]'
213c215
<       '(nosuid)suid[use suid and sgib bits]'
---
>       '(nosuid)suid[use suid and sgid bits]'
306,307c308
<       '(noauto)auto[can be mounted with -a]'
<       '(rw suid dev exec auto nouser async)defaults[use default options]'
---
>       '(rw suid dev exec async)defaults[use default options]'
309a311
>       '(nomand)mand[allow mandatory locks]'
311d312
<       '(auto)noauto[can only be mounted explicitly]'
313a315
>       "(mand)nomand[don'tallow mandatory locks]"
315d316
<       '(user)nouser[can only be mounted by root]'
319c320
<       '(nosuid)suid[use suid and sgib bits]'
---
>       '(nosuid)suid[use suid and sgid bits]'
326a328,333
>     _fs_adfs=(
>       'uid[set owner of root]:user ID'
>       'gid[set group of root]:group ID'
>       'ownmask[permission mask for ADFS "owner" permissions]:mask (octal)'
>       'othmask[permission mask for ADFS "other" permissions]:mask (octal)'
>     )
341a349,353
>     _fs_devpts=(
>       "uid[set owner of newly created pty's]:user ID"
>       "gid[set group of newly created pty's]:group ID"
>       "mode[set mode of newly created pty's]:file permission bits"
>     )
342a355,356
>       '(noacl)acl[support POSIX access control lists]'
>       '(acl)noacl[do not support POSIX access control lists]'
351a366,369
>       'nobh[do not attach buffer_heads to file pagecache]'
>       'nouid32[disable 32-bit UIDs and GIDs]'
>       '(orlov)oldalloc[use old allocator for new inodes]'
>       '(oldalloc)orlov[use orlov allocator for new inodes]'
355c373,374
<       'nouid32[disable 32-bit UIDs and GIDs]'
---
>       '(nouser_xattr)user_xattr[support user extended attributes]'
>       '(user_xattr)nouser_xattr[do not support user extended attributes]'
379a399
>       'commit[specify commit sync interval for data and metadata]:seconds'
389a410,419
>     _fs_hfs=(
>       'creator[specify creator value]:creator'
>       'type[specify type value]:type'
>       'umask[specify umask]:umask value (octal)'
>       'dir_umask[specify umask for directories only]:umask value (octal)'
>       'file_umask[specify umask for files only]:umask value (octal)'
>       'session[specify CDROM session to mount]:session'
>       'part[specify partition number from device to use]:part'
>       'quiet[do not complain about invalid mount options]'
>     )
413a444,450
>     _fs_jfs=(
>       'iocharset[character set when converting from unicode to ascii]:character set'
>       'resize[resize volume to specified number of blocks]:blocks'
>       '(integrity)nointegrity[do not write to the journal]'
>       '(nointegrity)integrity[commit metadata changes to the journal]'
>       'errors[specify behavior on error]:error behavior:((continue\:ignore\ errors remount-ro\:remount\ file\ system\ read-only panic\:panic\ and\ halt\ system))'
>     )
422c459
<     )      
---
>     )
446a484
>       'nostrict[unset strict conformance]'
456a495,505
>     _fs_usbfs=(
>       'devuid[set owner of device files]:user ID'
>       'devgid[set group of device files]:group ID'
>       'devmode[set mode of device files]:file permission bits'
>       'busuid[set owner of bus directories]:user ID'
>       'busgid[set group of bus directories]:group ID'
>       'busmode[set mode of bus directories]:file permission bits'
>       'listuid[set owner of file devices]:user ID'
>       'listgid[set group of file devices]:group ID'
>       'listmode[set mode of file devices]:file permission bits'
>     )
467a517
>       'nouuid[ignore the filesystem uuid]'
698a749
>         "(-V -h)-i[don't call /sbin/umount.<fs> helper]"
801c852
<   local dev_tmp mp_tmp mline
---
>   local dev_tmp dpath_tmp mp_tmp mline
816a868,870
>   dpath_tmp=( "${(@M)dev_tmp:#/*}" )
>   dev_tmp=( "${(@)dev_tmp:#/*}" )
> 
818,819c872,874
<     'devices:device:compadd -a dev_tmp' \
<     'directories:mount point:compadd -a mp_tmp' && ret=0
---
>     'device-labels:device label:compadd -a dev_tmp' \
>     'device-paths: device path:_canonical_paths -A dpath_tmp -N device-paths device\ path' \
>     'directories:mount point:_canonical_paths -A mp_tmp -N directories mount\ point' && ret=0
Regards,
Ramkumar.

-- System Information:
Debian Release: testing/unstable
  APT prefers testing
  APT policy: (101, 'testing')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/dash
Kernel: Linux 2.6.16-beyond2
Locale: LANG=en_IN, LC_CTYPE=en_IN (charmap=UTF-8)

Versions of packages zsh depends on:
ii  debconf [debconf-2.0]         1.5.0      Debian configuration management sy
ii  libc6                         2.3.6-7    GNU C Library: Shared libraries
ii  libncurses5                   5.5-1.1    Shared libraries for terminal hand

Versions of packages zsh recommends:
ii  libcap1                       1:1.10-14  support for getting/setting POSIX.
ii  libpcre3                      6.4-2      Perl 5 Compatible Regular Expressi

-- no debconf information

-- 
WARN_(accel)("msg null; should hang here to be win compatible\n");
                                   -- WINE source code

Reply via email to