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

PATCH: _regex_arguments, _apt_arguments and _apt-get



I tried to modify _apt-get to perfection.

Since `apt' has slightly peculiar command line parsing library, I
decide to make and use the function `_regex_arguments' more primitive
and powerful than `_arguments'.

--- /dev/null	Thu Mar  4 02:20:11 1999
+++ Completion/Base/_regex_arguments	Wed Sep  8 20:14:58 1999
@@ -0,0 +1,396 @@
+#autoload
+
+## usage: _regex_arguments funcname regex
+
+# _regex_arguments compiles `regex' and emit the result of the state
+# machine into the function `funcname'. `funcname' parses a command line
+# according to `regex' and evaluate appropriate actions in `regex'. Before
+# parsing the command line string is genereted by concatinating `words'
+# (before `PREFIX') and `PREFIX' with a separator NUL ($'\0').
+
+# The `regex' is defined as follows.
+
+## regex word definition:
+
+# elt-pattern = "/" ( pattern | "[]" )	# cutoff
+#	      | "%" pattern		# non-cutoff
+# lookahead = "@" pattern
+# parse-action = "-" zsh-code-to-eval
+# complete-action = "!" zsh-code-to-eval
+
+## regex word sequence definition:
+
+# element = elt-pattern [ lookahead ] [ parse-action ] [ complete-action ]
+#
+# regex = element 
+#	| "(" regex ")"
+#	| regex "#"
+#	| regex regex
+#	| regex "|" regex
+#	| void
+#	| null
+#
+# NOTE: void and null has no explicit representation. However null can
+# be represent with empty words such as \( \).
+
+# example: (in zsh quoted form)
+
+# $'[^\0]#\0' \#	: zero or more words
+
+## auxiliary functions definition:
+
+# fst : a * b -> a
+# snd : a * b -> b
+# fst( (x, y) ) = x
+# snd( (x, y) ) = y
+
+# nullable : regex -> bool
+# first : regex -> list of element
+# match : string * list of element -> element + {bottom}
+# right : string * element -> string
+# left : string * element -> string
+# next : regex * element -> regex + {bottom}
+# trans : string * string * regex -> (string * string * regex) + {bottom}
+
+# nullable(void) = false
+# nullable(null) = true
+# nullable(e) = false
+# nullable(r #) = true
+# nullable(r1 r2) = nullable(r1) and nullable(r2)
+# nullable(r1 | r2) = nullable(r1) or nullable(r2)
+
+# first(void) = {}
+# first(null) = {}
+# first(e) = [ e ]
+# first(r #) = first(r)
+# first(r1 r2) = nullable(r1) ? first(r1) ++ first(r2) : first(r1)
+# first(r1 | r2) = first(r1) ++ first(r2)
+
+# match(s, []) = bottom
+# match(s, [e1, e2, ...]) = e	if [[ $s = $elt-pattern[e]$lookahead[e]* ]]
+#		   	  | match(s, [e2, ...])	otherwise
+
+# right(s, e) = ${s##$elt-pattern[e]}
+# left(s, e) = ${(M)s##$elt-pattern[e]}
+
+### XXX: It can treat lookaheads if zsh provide $1, $2, ... in perl.
+
+# next(void, e) = bottom
+# next(null, e) = bottom
+# next(e1, e0) = e1 eq e0 ? null : bottom	# eq is test operator of identity equality.
+# next(r #, e) = next(r, e) != bottom ? next(r, e) (r #) : bottom
+# next(r1 r2, e) = next(r1, e) != bottom ? next(r1, e) r2 : next(r2, e)
+# next(r1 | r2, e) = next(r1, e) != bottom ? next(r1, e) : next(r2, e)
+
+# trans( (t, s, r) ) = ( (cutoff(e) ? '' : t ++ left(s, e)), right(s, e), next(r, e) )
+#   where e = match(s, first(r))
+
+# NOTE: This `next' definition is slightly different to ordinaly one.
+# This definition uses only one element of first(r) for transition
+# instead of all elements of first(r).
+
+# If _regex_arguments takes the regex r0, the first state of the state
+# machine is r0.  The state of the state machine transit as follows.
+
+# ('', s0, r0) -> trans('', s0, r0) = (t1, s1, r1) -> trans(t1, s1, r1) -> ... 
+
+# If the state is reached to bottom, the state transition is stopped.
+
+# ... -> (tN, sN, rN) -> bottom
+
+# For each transitions (tI, sI, rI) to trans(tI, sI, rI), the state
+# machine evaluate parse-action bound to match(sI, first(rI)).
+
+# In parse-action bound to match(sI, first(rI)) = e, it can refer variables:
+#  _ra_left : tI+1
+#  _ra_match : left(sI, e)
+#  _ra_right : sI+1
+
+# If the state transition is stopped, the state machine evaluate
+# complete-actions bound to first(rN) if tN and sN does not contain NUL.
+# When complete-actions are evaluated, completion focus is restricted to
+# tN ++ sN. (This is reason of tN and sN cannot contain NUL when
+# completion.)
+# Also, if there are last transitions that does not cut off the string
+# (tJ ++ sJ = tJ+1 ++ sJ+1 = ... = tN-1 ++ sN-1 = tN ++ sN),
+# complete-actions bound to them
+# --- match(sJ, first(rJ)), ..., match(sN-1, first(rN-1)) --- are also
+# evaluated before complete-actions bound to first(rN).
+
+# example:
+
+# compdef _tst tst
+
+# _regex_arguments _tst /$'[^\0]#\0' /$'[^\0]#\0' '!compadd aaa'
+#  _tst complete `aaa' for first argument.
+#  First $'[^\0]#\0' is required to match with command name.
+
+# _regex_arguments _tst /$'[^\0]#\0' \( /$'[^\0]#\0' '!compadd aaa' /$'[^\0]#\0' !'compadd bbb' \) \#
+#  _tst complete `aaa' for (2i+1)th argument and `bbb' for (2i)th argument.
+
+# _regex_arguments _tst /$'[^\0]#\0' \( /$'[^\0]#\0' '!compadd aaa' \| /$'[^\0]#\0' !'compadd bbb' \) \#
+#  _tst complete `aaa' or `bbb'.
+
+## Recursive decent regex parser
+
+_ra_parse_elt () {
+  : index=$index "[$regex[$index]]"
+  local state
+  if (( $#regex < index )); then
+    return 1
+  else
+    case "$regex[index]" in
+      [/%]*) state=$index
+          first=($state)
+	  last=($state)
+	  nullable=
+	  case "${regex[index][1]}" in
+	    /) cutoff[$state]=yes ;;
+	    %) cutoff[$state]= ;;
+	  esac
+          pattern[$state]="${regex[index++][2,-1]}"
+	  [[ -n "$pattern[$state]" ]] && pattern[$state]="($pattern[$state])"
+	  if [[ $index -le $#regex && $regex[index] = @* ]]; then
+	    lookahead[$state]="${regex[index++][2,-1]}"
+	    [[ -n "$lookahead[$state]" ]] && lookahead[$state]="($lookahead[$state])"
+	  else
+	    lookahead[$state]=""
+	  fi
+	  if [[ $index -le $#regex && $regex[index] = -* ]]; then
+	    parse_action[$state]="${regex[index++][2,-1]}"
+	  else
+	    parse_action[$state]=""
+	  fi
+	  if [[ $index -le $#regex && $regex[index] = \!* ]]; then
+	    complete_action[$state]="${regex[index++][2,-1]}"
+	  else
+	    complete_action[$state]=""
+	  fi
+	  ;;
+      \() (( index++ ))
+          _ra_parse_alt || return 1
+	  [[ $index -le $#regex && "$regex[$index]" = \) ]] || return 1
+	  (( index++ ))
+	  ;;
+      *)  return 1
+          ;;
+    esac
+  fi
+
+  return 0
+}
+
+_ra_parse_clo () {
+  : index=$index "[$regex[$index]]"
+  _ra_parse_elt || return 1
+
+  if (( index <= $#regex )) && [[ "$regex[$index]" = \# ]]; then
+    (( index++ ))
+    nullable=yes
+
+    for i in $last; do tbl[$i]="$tbl[$i] $first"; done
+  fi
+
+  return 0
+}
+
+_ra_parse_seq () {
+  : index=$index "[$regex[$index]]"
+  local last_seq
+  local first_seq nullable_seq
+  first_seq=()
+  nullable_seq=yes
+
+  _ra_parse_clo || {
+    first=()
+    last=()
+    nullable=yes
+    return 0
+  }
+  first_seq=($first)
+  last_seq=($last)
+  [[ -n "$nullable" ]] || nullable_seq=
+
+  while :; do
+    _ra_parse_clo || break
+    for i in $last_seq; do tbl[$i]="${tbl[$i]} $first"; done
+    [[ -n "$nullable_seq" ]] && first_seq=($first_seq $first)
+    [[ -n "$nullable" ]] || { nullable_seq= last_seq=() }
+    last_seq=($last_seq $last)
+  done
+
+  first=($first_seq)
+  nullable=$nullable_seq
+  last=($last_seq)
+  return 0
+}
+
+_ra_parse_alt () {
+  : index=$index "[$regex[$index]]"
+  local last_alt
+  local first_alt nullable_alt 
+  first_alt=()
+  nullable_alt=
+
+  _ra_parse_seq || return 1
+  first_alt=($first_alt $first)
+  last_alt=($last_alt $last)
+  [[ -n "$nullable" ]] && nullable_alt=yes
+
+  while :; do
+    (( index <= $#regex )) || break
+    [[ "$regex[$index]" = \| ]] || break
+    (( index++ ))
+
+    _ra_parse_seq || break
+    first_alt=($first_alt $first)
+    last_alt=($last_alt $last)
+    [[ -n "$nullable" ]] && nullable_alt=yes
+  done
+
+  first=($first_alt)
+  last=($last_alt)
+  nullable=$nullable_alt
+  return 0
+}
+
+## function generator
+
+_ra_gen_func () {
+  local old new
+  local state next index
+  local start="${(j/:/)first}"
+
+  old=()
+  new=($start)
+
+  print -lr - \
+    "$funcname () {" \
+      'setopt localoptions extendedglob' \
+      'local _ra_state _ra_left _ra_match _ra_right _ra_actions _ra_tmp' \
+      "_ra_state='$start'" \
+      '_ra_left=' \
+      '_ra_right="${(pj:\0:)${(@)words[1,CURRENT - 1]:Q}}"$'\''\0'\''"$PREFIX"' \
+      '_ra_actions=()' \
+      'while :; do' \
+	'case "$_ra_state" in'
+
+  while (( $#new )); do
+    state="$new[1]"
+    shift new
+    old=("$old[@]" "$state")
+
+    print -lr - \
+	"$state)" \
+	  'case "$_ra_right" in'
+
+    for index in ${(s/:/)state}; do
+      if [[ "$pattern[$index]" != "([])" ]]; then
+	next="${(j/:/)${(@)=tbl[$index]}}"
+	print -lr - \
+	      "$pattern[$index]$lookahead[$index]*)"
+	if [[ -n "$pattern[$index]" ]]; then
+	  if [[ -n "$cutoff[$index]" ]]; then
+	    print -lr - \
+		  '_ra_match="${(M)_ra_right##'"$pattern[$index]"'}"' \
+		  '_ra_right="$_ra_right[$#_ra_match + 1, -1]"' \
+		  '_ra_left=' \
+		  'if (( $#_ra_match )); then' \
+		    '_ra_actions=()'
+	    if [[ -n "${complete_action[$index]:q}" ]]; then
+	      print -lr - \
+		  'else' \
+		    '_ra_actions=("$_ra_actions[@]" '"${complete_action[$index]:q}"')'
+	    fi
+	    print -lr - \
+		  'fi'
+	  else
+	    print -lr - \
+		  '_ra_match="${(M)_ra_right##'"$pattern[$index]"'}"' \
+		  '_ra_right="$_ra_right[$#_ra_match + 1, -1]"' \
+		  '_ra_left="$_ra_left$_ra_match"'
+	    if [[ -n "${complete_action[$index]:q}" ]]; then
+	      print -lr - \
+		  '_ra_actions=("$_ra_actions[@]" '"${complete_action[$index]:q}"')'
+	    fi
+	  fi
+	else
+	  print -lr - \
+		'_ra_match=' \
+		'_ra_actions=("$_ra_actions[@]" '"${complete_action[$index]:q}"')'
+	fi
+	print -lr - \
+		"$parse_action[$index]"
+	if [[ -n $next ]]; then
+	  print -lr - \
+		"_ra_state=$next"
+	  (( $old[(I)$next] || $new[(I)$next] )) || new=($next "$new[@]")
+	else
+	  print -lr - \
+		'_message "no arg"' \
+		'break'
+	fi
+	print -lr - \
+		';;'
+      fi
+    done
+
+    print -lr - \
+	    '*)' \
+	      'if [[ "$_ra_left$_ra_right" = *$'\''\0'\''* ]]; then' \
+		'_message "parse failed before current word"' \
+	      'else' \
+		'compset -p $(( $#PREFIX - $#_ra_right - $#_ra_left ))'
+
+    print -lr - \
+		'for _ra_tmp in $_ra_actions; do' \
+		  'eval "$_ra_tmp"' \
+		'done'
+    for index in ${(s/:/)state}; do
+      print -lr - \
+		"$complete_action[$index]"
+    done
+
+    print -lr - \
+	      'fi' \
+	      'break' \
+	      ';;' \
+	  'esac' \
+	  ';;'
+  done
+
+  print -lr - \
+	'esac' \
+      'done' \
+    '}'
+}
+
+_regex_arguments () {
+  setopt localoptions extendedglob
+
+  local funcname="_regex_arguments_tmp"
+  local funcdef
+
+  typeset -A tbl cutoff pattern lookahead parse_action complete_action
+  local regex index first last nullable
+  local i state next
+
+  funcname="$1"
+  shift
+
+  regex=("$@")
+  index=1
+  tbl=()
+  pattern=()
+  lookahead=()
+  parse_action=()
+  complete_action=()
+  _ra_parse_alt
+
+  funcdef="$(_ra_gen_func)"
+
+  unfunction "$funcname" 2>/dev/null
+  eval "${(F)funcdef}"
+}
+
+_regex_arguments "$@"
--- /dev/null	Thu Mar  4 02:20:11 1999
+++ Completion/Debian/_apt_arguments	Wed Sep  8 19:54:43 1999
@@ -0,0 +1,230 @@
+#autoload
+
+# short_bool=(h v d b s y f u m)
+# short_intlevel=(q)
+# short_configfile=(c)
+# short_arbitem=(o)
+# 
+# long_bool=(help version download-only compile build simulate just-print recon
+#   no-act yes assume-yes fix-broken show-upgraded ignore-missing no-download
+#   fix-missing ignore-hold no-upgrade force-yes print-uris)
+# long_intlevel=(quiet silent)
+# long_configfile=(config-file)
+# long_arbitem=(option)
+
+###
+
+local funcname
+funcname="$1"
+shift
+
+local short_seq false true bool bool_ __bool_ intlevel word word1 nul
+local comp_bool comp_intlevel comp_configfile comp_arbitem comp_long
+local regex_short regex_long regex_message regex_action
+
+regex_action=("$@")
+
+short_seq="(${(j:|:)short_bool}|${(j:|:)short_intlevel})#"
+
+false=(no false without off disable)
+true=(yes true with on enable)
+bool=($false $true)
+
+bool_=(${^bool}-)
+__bool_=(--$^bool_)
+
+intlevel='[0-9]##'
+
+word=$'[^\0]#\0'
+word1=$'[^\0]##\0'
+
+nul=$'\0'
+
+comp_bool='compadd "$expl_bool[@]" '"$bool"
+comp_intlevel= #"_message 'intlevel'"
+comp_configfile='_files "$expl_configfile[@]"'
+comp_arbitem= #"_message 'Foo::Bar=bar'"
+
+comp_long="\
+tmp1=\${(kj:|:)long_to_option[(R)\${(kj:|:)~options[(R)*~0]}]}
+tmp2=(--\${(M)^long_bool:#\$~tmp1} --\${(M)^long_intlevel:#\$~tmp1})
+compadd \"\$expl_opt[@]\" - \$tmp2
+tmp2=(--\${(M)^long_configfile:#\$~tmp1} --\${(M)^long_arbitem:#\$~tmp1})
+compadd \"\$expl_opt[@]\" -S= - \$tmp2
+compadd \"\$expl_opt[@]\" -S '' - $__bool_"
+
+regex_short=(
+  %-
+  \(
+    /"$short_seq(${(j:|:)short_bool})($nul(${(j:|:)bool})|(${(j:|:)bool})|)$nul"
+      -"apt_consume_short \${_ra_match%%($nul(${(j:|:)bool})|(${(j:|:)bool})|)$nul}" \|
+    /"$short_seq(${(j:|:)short_bool})="
+      -"apt_consume_short \${_ra_match%=}"
+      \( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
+    /"$short_seq(${(j:|:)short_intlevel})($nul$intlevel|$intlevel|)$nul"
+      -"apt_consume_short \${_ra_match%%($nul$intlevel|$intlevel|)$nul}" \|
+    /"$short_seq(${(j:|:)short_intlevel})="
+      -"apt_consume_short \${_ra_match%=}"
+      \( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
+    /"$short_seq(${(j:|:)short_configfile})(=|)"
+      -"apt_consume_short \${_ra_match%=}"
+      \( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
+    /"$short_seq(${(j:|:)short_arbitem})(=|)"
+      -"apt_consume_short \${_ra_match%=}"
+      \( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
+    /"[]" !"{
+	      if [[ \$PREFIX = -$short_seq ]]; then
+		apt_consume_short \${PREFIX[2,-1]}
+		tmp1=(\${(k)short_to_option[(R)\${(kj:|:)~options[(R)*~0]}]})
+		tmp2=(-\${^tmp1})
+		compadd \"\$expl_opt[@]\" -y \"(\$tmp2)\" - \${PREFIX}\${^tmp1}
+	      fi
+	      $comp_long
+	    }"
+  \)
+)
+
+regex_long=(
+  %--
+  \(
+    /"(${(j:|:)long_bool})="
+      -"apt_consume_long \${_ra_match%=}"
+      \( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
+    /"(${(j:|:)long_bool})$nul"
+      -"apt_consume_long \${_ra_match%$nul}"
+      /"((${(j:|:)bool})$nul|)" !"$comp_bool" \|
+    /"(${(j:|:)long_intlevel})="
+      -"apt_consume_long \${_ra_match%=}"
+      \( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
+    /"(${(j:|:)long_intlevel})$nul"
+      -"apt_consume_long \${_ra_match%$nul}"
+      /"($intlevel$nul|)" !"$comp_intlevel" \|
+    /"(${(j:|:)long_configfile})$nul"
+      -"apt_consume_long \${_ra_match%$nul}"
+      /"$word" !"$comp_configfile" \|
+    /"(${(j:|:)long_configfile})="
+      -"apt_consume_long \${_ra_match%=}"
+      \( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
+    /"(${(j:|:)long_arbitem})$nul"
+      -"apt_consume_long \${_ra_match%$nul}"
+      /"$word" !"$comp_arbitem" \|
+    /"(${(j:|:)long_arbitem})="
+      -"apt_consume_long \${_ra_match%=}"
+      \( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
+    %"(${(j:|:)bool})-"
+    \(
+      /"(${(j:|:)long_bool})="
+	-"apt_consume_long \${_ra_match%=}"
+        \( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
+      /"(${(j:|:)long_bool})$nul"
+	-"apt_consume_long \${_ra_match%$nul}"
+        /"((${(j:|:)bool})$nul|)" !"$comp_bool" \|
+      /"(${(j:|:)long_intlevel})$nul"
+	-"apt_consume_long \${_ra_match%$nul}"
+        /"$intlevel" !"$comp_intlevel" /"$nul" \|
+      /"(${(j:|:)long_intlevel})="
+	-"apt_consume_long \${_ra_match%=}"
+        \( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
+      /"(${(j:|:)long_intlevel})$nul"
+	-"apt_consume_long \${_ra_match%$nul}"
+        /"($intlevel$nul|)" !"$comp_intlevel" \|
+      /"(${(j:|:)long_configfile})$nul"
+	-"apt_consume_long \${_ra_match%$nul}"
+        /"$word" !"$comp_configfile" \|
+      /"(${(j:|:)long_configfile})="
+	-"apt_consume_long \${_ra_match%=}"
+        \( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
+      /"(${(j:|:)long_arbitem})$nul"
+	-"apt_consume_long \${_ra_match%$nul}"
+        /"$word" !"$comp_arbitem" \|
+      /"(${(j:|:)long_arbitem})="
+	-"apt_consume_long \${_ra_match%=}"
+        \( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
+      /"(${(j:|:)short_bool})="
+	-"apt_consume_short \${_ra_match[-2]}"
+        \( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
+      /"(${(j:|:)short_bool})$nul"
+	-"apt_consume_short \${_ra_match[-2]}"
+        /"((${(j:|:)bool})$nul|)" !"$comp_bool" \|
+      /"(${(j:|:)short_intlevel})="
+	-"apt_consume_short \${_ra_match[-2]}"
+        \( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
+      /"(${(j:|:)short_intlevel})$nul"
+	-"apt_consume_short \${_ra_match[-2]}"
+        /"($intlevel$nul|)" !"$comp_intlevel" \|
+      /"(${(j:|:)short_configfile})$nul"
+	-"apt_consume_short \${_ra_match[-2]}"
+        /"$word" !"$comp_configfile" \|
+      /"(${(j:|:)short_configfile})="
+	-"apt_consume_short \${_ra_match[-2]}"
+        \( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
+      /"(${(j:|:)short_arbitem})$nul"
+	-"apt_consume_short \${_ra_match[-2]}"
+        /"$word" !"$comp_arbitem" \|
+      /"(${(j:|:)short_arbitem})="
+	-"apt_consume_short \${_ra_match[-2]}"
+        \( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
+      /"[]" !"{ tmp1=\${(kj:|:)long_to_option[(R)\${(kj:|:)~options[(R)*~0]}]}
+		tmp2=(\$_ra_left\${(M)^long_bool:#\$~tmp1} \$_ra_left\${(M)^long_intlevel:#\$~tmp1})
+		compadd \"\$expl_opt[@]\" - \$tmp2
+		tmp2=(\$_ra_left\${(M)^long_configfile:#\$~tmp1} \$_ra_left\${(M)^long_arbitem:#\$~tmp1})
+		compadd \"\$expl_opt[@]\" -S= - \$tmp2
+		tmp1=\${(kj:|:)short_to_option[(R)\${(kj:|:)~options[(R)*~0]}]}
+		tmp2=(\$_ra_left\${(M)^short_bool:#\$~tmp1} \$_ra_left\${(M)^short_intlevel:#\$~tmp1})
+		compadd \"\$expl_opt[@]\" - \$tmp2
+		tmp2=(\$_ra_left\${(M)^short_configfile:#\$~tmp1} \$_ra_left\${(M)^short_arbitem:#\$~tmp1})
+		compadd \"\$expl_opt[@]\" -S= - \$tmp2
+	      }"
+    \) \|
+    /"[]" !"{
+	      $comp_long
+	    }"
+  \)
+)
+
+regex_message=(
+  /"[]" !"[[ -prefix - || -z \"\$compconfig[option_prefix]\" ]] && {
+	    if [[ \$PREFIX = -$short_seq ]]; then
+	      apt_consume_short \${PREFIX[2,-1]}
+	      tmp1=(\${(k)short_to_option[(R)\${(kj:|:)~options[(R)*~0]}]})
+	      tmp2=(-\${^tmp1})
+	      compadd \"\$expl_opt[@]\" -y \"(\$tmp2)\" - \${PREFIX}\${^tmp1}
+	    elif [[ -z "\$PREFIX" ]]; then
+	      tmp1=(-\${(k)^short_to_option[(R)\${(kj:|:)~options[(R)*~0]}]})
+	      compadd \"\$expl_opt[@]\" - \$tmp1
+	    fi
+	    $comp_long
+	  }"
+)
+
+apt_consume_short () {
+  local short opt
+  for short in ${(s::)1}; do
+    opt="$short_to_option[$short]"
+    (( 0 < options[$opt] && options[$opt]-- ))
+  done
+}
+
+apt_consume_long () {
+  local long opt
+  opt="$long_to_option[$1]"
+  (( 0 < options[$opt] && options[$opt]-- ))
+}
+
+_regex_arguments "${funcname}_sm" /"$word" \( "$regex_long[@]" \| "$regex_short[@]" \| "$regex_message[@]" \) \# "$regex_action[@]"
+
+eval "$funcname () {
+  local short_bool short_intlevel short_configfile short_arbitem
+  local long_bool long_intlevel long_configfile long_arbitem
+  short_bool=($short_bool)
+  short_intlevel=($short_intlevel)
+  short_configfile=($short_configfile)
+  short_arbitem=($short_arbitem)
+  long_bool=($long_bool)
+  long_intlevel=($long_intlevel)
+  long_configfile=($long_configfile)
+  long_arbitem=($long_arbitem)
+
+  ${funcname}_sm
+}"
+
Index: Completion/Debian/_apt-get
===================================================================
RCS file: /projects/zsh/zsh/Completion/Debian/_apt-get,v
retrieving revision 1.1.1.3
diff -u -F^( -r1.1.1.3 _apt-get
--- _apt-get	1999/09/05 15:11:49	1.1.1.3
+++ _apt-get	1999/09/08 12:55:38
@@ -1,40 +1,118 @@
 #compdef apt-get
 
+local short_bool short_intlevel short_configfile short_arbitem
+local long_bool long_intlevel long_configfile long_arbitem
+local action
+
+short_bool=(h v d b s y f u m)
+short_intlevel=(q)
+short_configfile=(c)
+short_arbitem=(o)
+
+long_bool=(help version download-only compile build simulate just-print recon
+  no-act yes assume-yes fix-broken show-upgraded ignore-missing no-download
+  fix-missing ignore-hold no-upgrade force-yes print-uris)
+long_intlevel=(quiet silent)
+long_configfile=(config-file)
+long_arbitem=(option)
+
+action=(update upgrade install remove dist-upgrade dselect-upgrade clean
+  autoclean check source help)
+
+comp_action='compadd "$expl_action[@]" '"$action"
+
+regex_action=(
+ \(
+    /$'update\0' \|
+    /$'upgrade\0' \|
+    /$'install\0' /$'[^\0]#\0' !'_deb_packages uninstalled "$expl_packages[@]" || _deb_packages installed "$expl_packages[@]" ' \# \|
+    /$'remove\0' /$'[^\0]#\0' !'_deb_packages installed "$expl_packages[@]"' \# \|
+    /$'dist-upgrade\0' \|
+    /$'dselect-upgrade\0' \|
+    /$'clean\0' \|
+    /$'autoclean\0' \|
+    /$'check\0' \|
+    /$'source\0' /$'[^\0]#\0' !'_deb_packages avail "$expl_packages[@]"' \# \|
+    /$'help\0' \|
+    /"[]"	!"$comp_action"
+  \)
+)
+
+_apt_arguments _apt-get_sm "$regex_action[@]"
+
 _apt-get () {
-  # This doesn't handle command line of apt completely since command line
-  # parsing library for apt is too complex to handle by _arguments.
-  _arguments -s \
-    -{,-no-}d --{,no-}download-only \
-    -{,-no-}f --{,no-}fix-broken \
-    -{,-no-}h --{,no-}help \
-    -{,-no-}v --{,no-}version \
-    -{,-no-}m --{,no-}ignore-missing \
-    --{,no-}fix-missing \
-    --{,no-}no-download \
-    \*-{,-no-}q \*--{,no-}{quiet,silent} \
-    -{,-no-}s --{,no-}{simulate,just-print,dry-run,recon,no-act} \
-    -{,-no-}y --{,no-}{yes,assume-yes} \
-    -{,-no-}u --{,no-}show-upgraded \
-    -{,-no-}b --{,no-}{compile,build} \
-    --{,no-}ignore-hold \
-    --{,no-}no-upgrade \
-    --{,no-}force-yes \
-    --{,no-}print-uris \
-    {-{,-no-}c,--{,no-}config-file}':Configuration File:_files' \
-    {-o,--option}':Foo\:\:Bar=bar:' \
-    '*::command and packages:_apt-get_args'
-}
-
-_apt-get_args () {
-  if (( CURRENT == 1 )); then
-    compadd "$@" - update upgrade dselect-upgrade dist-upgrade install remove source check clean autoclean help
-  else
-    case "$words[1]" in
-      install) _deb_packages uninstalled "$@" || _deb_packages installed "$@";;
-      remove) _deb_packages installed "$@";;
-      *) _deb_packages avail "$@";;
-    esac
-  fi
+  local tmp1 tmp2
+  local expl_action expl_opt expl_bool expl_configfile expl_packages
+  _description expl_action action
+  _description expl_opt option
+  _description expl_bool 'bool value'
+  _description expl_configfile 'config file'
+  _description expl_packages 'package'
+
+  typeset -A options short_to_option long_to_option
+
+  options=(
+    help		1
+    version		1
+    quiet		-1
+    download-only	1
+    compile		1
+    simulate		1
+    assume-yes		1
+    fix-broken		1
+    show-upgraded	1
+    no-download		1
+    fix-missing		1
+    ignore-hold		1
+    no-upgrade		1
+    force-yes		1
+    print-uris		1
+    config-file		1
+    option		-1
+  )
+
+  short_to_option=(
+    h help
+    v version
+    q quiet
+    d download-only
+    b compile
+    s simulate
+    y assume-yes
+    f fix-broken
+    u show-upgraded
+    m fix-missing
+    c config-file
+    o option
+  )
+
+  long_to_option=(
+    help		help
+    version		version
+    quiet		quiet
+    silent		quiet
+    download-only	download-only
+    compile		compile
+    build		compile
+    simulate		simulate
+    just-print		simulate
+    recon		simulate
+    no-act		simulate
+    yes			assume-yes
+    assume-yes		assume-yes
+    fix-broken		fix-broken
+    show-upgraded	show-upgraded
+    ignore-missing	fix-missing
+    no-download		no-download
+    ignore-hold		ignore-hold
+    no-upgrade		no-upgrade
+    force-yes		force-yes
+    print-uris		print-uris
+    config-file		config-file
+    option		option
+  )
+
+  _apt-get_sm
 }
 
 _apt-get "$@"
-- 
Tanaka Akira



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