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

[PATCH] Completion batch #3: Break _flags/_modes out of _chflags/_chmod



Moving on to more elaborate stuff:

1. Some of the new functions i was adding (to come in a subsequent batch) needed
   to re-use the logic for file flags and modes from _chflags and _chmod,
   respectively, so i broke those out into separate type functions called _flags
   and _modes.

2. I updated _flags so that it shows privileged flags when it sees that you're
   completing with sudo.

3. I updated _chflags and _chmod to use the new type functions.

4. I updated _chflags to show other users' files in addition to your own when it
   sees that you're completing with sudo.

5. I updated `find -perm` and `mkdir -m` to use _modes. (A cursory grep shows
   that _git and _mount might be able to use this too, but i didn't want to mess
   with them since i wasn't sure. I don't see any existing functions that want
   _flags.)

The changes to _chflags and _flags incorporate Matthew's just-merged
improvements from workers/42117, as well as some additional feedback he and
Eric gave me on IRC.

I didn't see many type functions using _values, but it seemed appropriate to
make use of the -O option here to pass arguments to compadd. Let me know if
there's a better way.

dana


diff --git a/Completion/BSD/Command/_chflags b/Completion/BSD/Command/_chflags
index ddf61b25e..f97d1cdd1 100644
--- a/Completion/BSD/Command/_chflags
+++ b/Completion/BSD/Command/_chflags
@@ -1,68 +1,8 @@
 #compdef chflags
 
-local args flag_descs flags own='-g *(-u$EUID)'
+local args own='-g *(-u$EUID)'
 
-flag_descs=(
-  uappnd 'user append-only'
-  uchg 'user immutable'
-)
-
-if (( ! EUID )); then
-  flag_descs+=(
-    arch archived
-    nodump nodump
-    sappnd 'system append-only'
-    schg 'system immutable'
-  )
-  unset own
-fi
-
-if [[ $OSTYPE = (darwin|dragonfly|freebsd|netbsd)* ]]; then
-  flag_descs+=(opaque opaque)
-
-  if [[ $OSTYPE = darwin* ]]; then
-    flag_descs+=(hidden hidden)
-  fi
-
-  if [[ $OSTYPE = (dragonfly|freebsd)* ]]; then
-    flag_descs+=(uunlnk 'user undeletable')
-    (( EUID )) || flag_descs+=(sunlnk 'system undeletable')
-  fi
-
-  [[ $OSTYPE = dragonflybsd* ]] && {
-    flag_descs+=(
-      cache XXX
-      nouhistory 'user nohistory'
-    )
-
-    (( EUID )) || flag_descs+=(
-      noscache XXX
-      noshistory 'system nohistory'
-    )
-  }
-
-  [[ $OSTYPE = freebsd* ]] && flag_descs+=(
-    uarch archive
-    uhidden hidden
-    uoffline offline
-    urdonly 'DOS, Windows and CIFS readonly'
-    ureparse 'Windows reparse point'
-    usparse 'sparse file'
-    usystem 'DOS, Windows and CIFS system'
-  )
-fi
-
-() {
-  for 1 2; do
-    if [[ $1 = no* ]]; then
-      flags+=("(${1#no})$1[set the $2 flag]"
-               "($1)${1#no}[unset the $2 flag]")
-    else
-      flags+=("(no$1)$1[set the $2 flag]"
-               "($1)no$1[unset the $2 flag]")
-    fi
-  done
-} $flag_descs
+(( ! EUID || $+_comp_priv_prefix )) && own=
 
 if [[ $OSTYPE = (darwin|dragonfly|freebsd)* ]]; then
   args=(
@@ -72,7 +12,7 @@ if [[ $OSTYPE = (darwin|dragonfly|freebsd)* ]]; then
 fi
 
 _arguments -s -A "-*" : $args \
-  ':file flag:_values -s , "file flags" $flags[@]' \
+  ': :_flags' \
   '*:file:_files "$own"' \
   - opth \
   '-h[act on symlinks]' \
diff --git a/Completion/BSD/Type/_flags b/Completion/BSD/Type/_flags
new file mode 100644
index 000000000..95044121c
--- /dev/null
+++ b/Completion/BSD/Type/_flags
@@ -0,0 +1,70 @@
+#autoload
+
+# Provides completion for file flags (formerly part of _chflags)
+
+local curcontext=$curcontext su=$(( ! EUID || $+_comp_priv_prefix ))
+local -a context line state state_descr copts=( "${@}" ) flags flag_descs
+local -A val_args
+
+flag_descs+=(
+  uappnd 'user append-only'
+  uchg 'user immutable'
+)
+
+if (( su )); then
+  flag_descs+=(
+    arch archived
+    nodump nodump
+    sappnd 'system append-only'
+    schg 'system immutable'
+  )
+fi
+
+if [[ $OSTYPE = (darwin|dragonfly|freebsd|netbsd)* ]]; then
+  flag_descs+=(opaque opaque)
+
+  if [[ $OSTYPE = darwin* ]]; then
+    flag_descs+=(hidden hidden)
+  fi
+
+  if [[ $OSTYPE = (dragonfly|freebsd)* ]]; then
+    flag_descs+=(uunlnk 'user undeletable')
+
+    (( su )) &&
+    flag_descs+=(sunlnk 'system undeletable')
+  fi
+
+  if [[ $OSTYPE = dragonfly* ]]; then
+    flag_descs+=(
+      cache XXX
+      nouhistory 'user nohistory'
+    )
+
+    (( su )) && flag_descs+=(
+      noscache XXX
+      noshistory 'system nohistory'
+    )
+  fi
+
+  [[ $OSTYPE = freebsd* ]] && flag_descs+=(
+    uarch archive
+    uhidden hidden
+    uoffline offline
+    urdonly 'DOS, Windows and CIFS readonly'
+    ureparse 'Windows reparse point'
+    usparse 'sparse file'
+    usystem 'DOS, Windows and CIFS system'
+  )
+fi
+
+for 1 2 in $flag_descs; do
+  if [[ $1 = no* ]]; then
+    flags+=("(${1#no})$1[set the $2 flag]"
+             "($1)${1#no}[unset the $2 flag]")
+  else
+    flags+=("(no$1)$1[set the $2 flag]"
+             "($1)no$1[unset the $2 flag]")
+  fi
+done
+
+_values -O copts -s , 'file flags' $flags
diff --git a/Completion/Unix/Command/_chmod b/Completion/Unix/Command/_chmod
index 85e6df1ae..80c6f33ca 100644
--- a/Completion/Unix/Command/_chmod
+++ b/Completion/Unix/Command/_chmod
@@ -3,7 +3,7 @@
 local curcontext="$curcontext" state line expl ret=1
 local -a args privs
 
-args=( '*:file:->files' '1:mode:->mode' )
+args=( '*: :->files' '1: :_modes' )
 
 if _pick_variant gnu=Free\ Soft unix --version; then
   args+=(
@@ -45,35 +45,12 @@ else
         '(1)-I[removes all inherited entries from named files ACLs]'
       )
     ;;
-    solaris*) privs=( 'l[mandatory locking]' ) ;;
   esac
 fi
 
 _arguments -C -s "$args[@]" && ret=0
 
 case "$state" in
-  mode)
-    compset -P \*,
-    compset -S ,\*
-    if [[ -prefix [0-7] ]]; then
-      _message -e number 'numeric mode'
-    elif compset -P '[a-z]#[+-=]'; then
-      _values -S '' privilege \
-	'r[read]' 'w[write]' 'x[execute]' \
-	's[set uid/gid]' 't[sticky]' \
-	'X[execute only if directory or executable to another]' \
-	"u[owner's current permissions]" \
-	"g[group's current permissions]" \
-	"o[other's current permissions]" \
-	"$privs[@]" && ret=0
-    else
-      suf=( -S '' )
-      compset -P '*'
-      _alternative -O suf \
-	'who:who:((u\:user g\:group a\:all o\:others))' \
-	'operators:operator:(+ - =)' && ret=0
-    fi
-  ;;
   files)
     if [[ -n $opt_args[--reference] ]]; then
       zmodload -F zsh/stat b:zstat 2>/dev/null
diff --git a/Completion/Unix/Command/_find b/Completion/Unix/Command/_find
index 3854d6cce..2bfb89825 100644
--- a/Completion/Unix/Command/_find
+++ b/Completion/Unix/Command/_find
@@ -139,7 +139,7 @@ _arguments -C $args \
   '*-nogroup' \
   '*-nouser' \
   '*-ok:program: _command_names -e:*\;::program arguments: _normal' \
-  '*-perm:file permission bits' \
+  '*-perm: :_modes' \
   '*-print' \
   '*-prune' \
   '*-size:file size (blocks)' \
diff --git a/Completion/Unix/Command/_mkdir b/Completion/Unix/Command/_mkdir
index 2850b405d..830a96162 100644
--- a/Completion/Unix/Command/_mkdir
+++ b/Completion/Unix/Command/_mkdir
@@ -4,7 +4,7 @@ local curcontext="$curcontext" state line expl args variant ret=1
 typeset -A opt_args
 
 args=(
-  '(-m --mode)'{-m,--mode=}'[set permission mode]:numeric mode'
+  '(-m --mode)'{-m,--mode=}'[set permission mode]: :_modes'
   '(-p --parents)'{-p,--parents}'[make parent directories as needed]'
   '(-)*: :->directories'
 )
diff --git a/Completion/Unix/Type/_modes b/Completion/Unix/Type/_modes
new file mode 100644
index 000000000..fbe4c9363
--- /dev/null
+++ b/Completion/Unix/Type/_modes
@@ -0,0 +1,37 @@
+#autoload
+
+# Provides completion for file modes (formerly part of _chmod)
+
+local curcontext=$curcontext
+local -a context line state state_descr copts=( "${@}" ) privs
+local -A val_args
+
+privs=(
+  'r[read]' 'w[write]' 'x[execute]'
+  's[set uid/gid]' 't[sticky]'
+  'X[execute only if directory or executable to another]'
+  "u[owner's current permissions]"
+  "g[group's current permissions]"
+  "o[others' current permissions]"
+)
+
+[[ $OSTYPE == solaris* ]] &&
+privs+=( 'l[mandatory locking]' )
+
+compset -P '*,'
+compset -S ',*'
+
+if [[ -prefix [0-7] ]]; then
+  _message -e number 'numeric mode'
+elif compset -P '[a-z]#[+-=]'; then
+  _values -O copts -S '' privilege $privs && return 0
+else
+  compset -P '*'
+  copts=( -S '' )
+  _alternative -O copts \
+    'who:who:((a\:all u\:owner g\:group o\:others))' \
+    'operators:operator:(+ - =)' \
+  && return 0
+fi
+
+return 1



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