about summary refs log tree commit diff
path: root/Completion
diff options
context:
space:
mode:
Diffstat (limited to 'Completion')
-rw-r--r--Completion/Base/_regex_arguments348
1 files changed, 32 insertions, 316 deletions
diff --git a/Completion/Base/_regex_arguments b/Completion/Base/_regex_arguments
index 653aeedbe..3d4bdd8b1 100644
--- a/Completion/Base/_regex_arguments
+++ b/Completion/Base/_regex_arguments
@@ -22,16 +22,17 @@
 # pattern = "/" ( glob | "[]" ) "/" [ "+" | "-" ]
 # lookahead = "%" glob "%"
 # guard = "-" zsh-code-to-eval
-# action = ":" zsh-code-to-eval
+# caction = ":" zsh-code-to-eval
+# action = "{" zsh-code-to-eval "}"
 
 ## regex word sequence definition:
 
-# element = pattern [ lookahead ] [ guard ] [ action ]
-#
+# element = pattern [ lookahead ] [ guard ] [ caction ]
+# 
 # regex = element 
 #	| "(" regex ")"
 #	| regex "#"
-#	| regex regex
+#	| ( regex | action ) #
 #	| regex "|" regex
 
 # example:
@@ -56,323 +57,38 @@
 # 1 : parse error
 # 2 : fatal parse error
 
-_ra_parse_elt () {
-  local state act
-  if (( $#regex < index )); then
-    return 1
-  else
-    case "$regex[index]" in
-      /*/([-+]|)) state=$index
-          first=($state)
-	  last=($state)
-	  nullable=
-	  case "$regex[index]" in 
-	    */+) cutoff[$state]=+;;
-	    */) cutoff[$state]=/;;
-	    */-) cutoff[$state]=-;;
-	  esac
-          pattern[$state]="${${regex[index++]#/}%/([-+]|)}"
-	  if [[ $pattern[$state] != "[]" ]]; then
-	    pattern[$state]="(#b)((#B)$pattern[$state])"
-	  fi
-	  if [[ $index -le $#regex && $regex[index] = %*% ]]; then
-	    lookahead[$state]="(#B)${regex[index++][2,-2]}"
-	  else
-	    lookahead[$state]=""
-	  fi
-	  if [[ $index -le $#regex && $regex[index] = -* ]]; then
-	    guard[$state]="${regex[index++][2,-1]}"
-	  else
-	    guard[$state]=""
-	  fi
-	  if [[ $index -le $#regex && $regex[index] = :* ]]; then
-	    act="${regex[index++][2,-1]}"
-	    action[$state]="$act"
-	    : ${actions[$act]::="${actions[$act]} $state"}
-	  else
-	    action[$state]=""
-	  fi
-	  ;;
-      \() (( index++ ))
-          _ra_parse_alt || return $?
-	  [[ $index -le $#regex && "$regex[$index]" = \) ]] || return 2
-	  (( index++ ))
-	  ;;
-      *)  return 1
-          ;;
-    esac
-  fi
-
-  return 0
-}
-
-_ra_parse_clo () {
-  _ra_parse_elt || return $?
-
-  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 () {
-  local last_seq
-  local first_seq nullable_seq
-  first_seq=()
-  nullable_seq=yes
-
-  _ra_parse_clo || {
-    if (( $? == 2 )); then
-      return 2
-    else
-      first=()
-      last=()
-      nullable=yes
-      return 0
-    fi
-  }
-  first_seq=($first)
-  last_seq=($last)
-  [[ -n "$nullable" ]] || nullable_seq=
-
-  while :; do
-    _ra_parse_clo || {
-      if (( $? == 2 )); then
-        return 2
-      else
-        break
-      fi
-    }
-    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 () {
-  local last_alt
-  local first_alt nullable_alt 
-  first_alt=()
-  nullable_alt=
-
-  _ra_parse_seq || return $?
-  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 || {
-      if (( $? == 2 )); then
-        return 2
-      else
-        break
-      fi
-    }
-    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 index
-  local test tmp
-  local start="0"
-
-  old=()
-  new=($start)
-
-  print -lr - \
-    "$funcname () {" \
-      'local _ra_state _ra_left _ra_right _ra_actions' \
-      "_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)"
-    _ra_gen_parse_state
-    print -lr - \
-	  ';;'
-  done
-
-  print -lr - \
-	'esac' \
-      'done' \
-      'while (( $#_ra_actions )); do' \
-	'case "$_ra_actions[1]" in'
-
-  for tmp in "${(@k)actions}"; do
-    if [[ "$tmp" != '' ]]; then
-      print -lr - "${(j:);&:)${=actions[$tmp]}})" $tmp ';;'
-    fi
-  done
-
-  print -lr - \
-	'esac' \
-	'shift _ra_actions' \
-      'done' \
-    '}'
-}
-
-_ra_gen_parse_state () {
-  local actions i p
-  test='if'
-  for index in $=tbl[$state]; do
-    if [[ "$pattern[$index]" != "[]" ]]; then
-      p="$pattern[$index]$lookahead[$index]*"
-      if [[ -z "$guard[$index]" ]]; then
-	print -lr - \
-	  "$test [[ \$_ra_right = \${~:-${(qqqq)p}} ]]"
-      else
-	print -lr - \
-	  "$test [[ \$_ra_right = \${~:-${(qqqq)p}} ]] && {" \
-	      "$guard[$index]" \
-	    "}"
-      fi
-      test='elif'
-      (( $old[(I)$index] || $new[(I)$index] )) || new=($index "$new[@]")
-      print -lr - \
-	  "then" \
-	    "_ra_state=$index" \
-	    '_ra_right="${_ra_right[mend[1] + 1, -1]}"'
-      actions=()
-      for i in $=tbl[$index]; do
-	if [[ -n $action[$i] ]]; then
-	  actions=($actions $i)
-	fi
-      done
-      case "$cutoff[$index]" in
-	+) print -lr - \
-	    '_ra_left="$_ra_left$match[1]"'
-	  if (( $#actions )); then
-	    print -lr - \
-	    "_ra_actions=($actions \$_ra_actions)"
-	  fi
-          ;;
-	/) print -lr - \
-	    '_ra_left='
-	  print -lr - \
-	    'if (( mend[1] )); then' \
-	      "_ra_actions=($actions)"
-	  if (( $#actions )); then
-	    print -lr - \
-	    'else' \
-	      "_ra_actions=($actions \$_ra_actions)"
-	  fi
-	  print -lr - \
-	    'fi'
-	  ;;
-	-) print -lr - \
-	    '_ra_left=' \
-	    "_ra_actions=($actions)"
-	  ;;
-      esac
-    fi
-  done
-
-  if [[ $test != 'if' ]]; then
-  # Some branchs are exists. But all of them are failed.
-    print -lr - \
-	  'else' \
-	    'if [[ "$_ra_left$_ra_right" = *$'\''\0'\''* ]]; then' \
-	      '_message "parse failed before current word"' \
-	      '_ra_actions=()' \
-	    'else' \
-	      'compset -p $(( $#PREFIX - $#_ra_right - $#_ra_left ))' \
-	    'fi' \
-	    'break' \
-	  'fi'
-  else
-  # There are no branch.
-    print -lr - \
-	  '_message "no more arguments"' \
-	  '_ra_actions=()' \
-	  'break'
-  fi
+_ra_comp () {
+  _ra_actions=("$_ra_actions[@]" "$1")
 }
 
 _regex_arguments () {
-  local funcname="_regex_arguments_tmp"
-  local funcdef
-
-  typeset -A tbl cutoff pattern lookahead guard action actions
-  local regex index first last nullable
-  local i state next
-
-  local cache_dir
-  zstyle -s ":completion${curcontext}:regex" cache-path cache_dir
-  [[ -z "$cache_dir" ]] && cache_dir="$HOME/.zsh/regex_arguments"
-  local cache_file="$cache_dir/$1"
-  local cache_test
-
-  if ! [[ -f "$cache_file" ]] || ! source "$cache_file" "$@"; then
-    funcname="$1"
-
-    regex=("${(@)argv[2,-1]}")
-    index=1
-    tbl=()
-    pattern=()
-    lookahead=()
-    guard=()
-    action=()
-    actions=()
-    _ra_parse_alt
-
-    if (( $? == 2 || index != $#regex + 1 )); then
-      if (( index != $#regex + 1 )); then
-	print "regex parse error at $index: $regex[index]" >&2
+  local regex funcname="$1"
+  shift
+  regex=(${@/(#b):(*)/":_ra_comp ${(qqqq)match[1]}"})
+
+  eval \
+  "$funcname"' () {
+    local _ra_p1 _ra_p2 _ra_left _ra_right _ra_com
+    local _ra_actions _ra_line="${(pj:\0:)${(@)words[1,CURRENT - 1]:Q}}"$'\''\0'\''"$PREFIX"
+    regexparse _ra_p1 _ra_p2 "$_ra_line" '"${(j: :)${(qqqq)regex[@]}}"'
+    case "$?" in
+    0|2) _message "no more arguments";;
+    1) 
+      if [[ "$_ra_line[_ra_p1 + 1, -1]" = *$'\''\0'\''* ]]; then
+	_message "parse failed before current word"
       else
-	print "regex parse error at $index (end)" >&2
+	: $#PREFIX - $#_ra_line + $_ra_p1 : $_ra_p2
+	_ra_left="$_ra_line[_ra_p1 + 1, _ra_p2]"
+	_ra_right="$_ra_line[_ra_p2 + 1, -1]"
+	compset -p $(( $#PREFIX - $#_ra_line + $_ra_p1 ))
+	for _ra_com in "$_ra_actions[@]"; do
+	  eval "$_ra_com"
+	done
       fi
-      return 1
-    fi
-
-    tbl[0]=" $first"
-
-    unfunction "$funcname" 2>/dev/null
-    funcdef="$(_ra_gen_func)"
-
-    if [[ -d "$cache_dir" && -w "$cache_dir" ]]; then
-      print -lr - \
-	'if [[ $# -eq '$#' && "$*" = '"${(qqqq)*}"' ]]; then' \
-	"$funcdef" \
-	'true; else false; fi' > "${cache_file}.$HOST.$$"
-      source "${cache_file}.$HOST.$$" "$@"
-      mv "${cache_file}.$HOST.$$" "${cache_file}"
-    else
-      source =(print -lr - "$funcdef")
-    fi
-  fi
+      ;;
+    3) _message "invalid regex";;
+    esac
+  }'
 }
 
 _regex_arguments "$@"