about summary refs log tree commit diff
path: root/Completion/Unix/Command/_openstack
diff options
context:
space:
mode:
authorSyphdias <syphdias+git@gmail.com>2021-03-18 23:23:16 +0100
committerOliver Kiddle <opk@zsh.org>2021-03-31 01:16:25 +0200
commit5d0bb152ef1486e1b38326e37e91e98295bc6946 (patch)
tree9fcea1515dcc82f65a3cd1a2a96bef78b542af0f /Completion/Unix/Command/_openstack
parent7518b20a01bd27a9246d9b040ba5f972ab686e62 (diff)
downloadzsh-5d0bb152ef1486e1b38326e37e91e98295bc6946.tar.gz
zsh-5d0bb152ef1486e1b38326e37e91e98295bc6946.tar.xz
zsh-5d0bb152ef1486e1b38326e37e91e98295bc6946.zip
48192: Fix _openstack completion for new style clients
Diffstat (limited to 'Completion/Unix/Command/_openstack')
-rw-r--r--Completion/Unix/Command/_openstack117
1 files changed, 64 insertions, 53 deletions
diff --git a/Completion/Unix/Command/_openstack b/Completion/Unix/Command/_openstack
index fcb704ac8..d55686b80 100644
--- a/Completion/Unix/Command/_openstack
+++ b/Completion/Unix/Command/_openstack
@@ -34,8 +34,6 @@ if (( ! $+_cache_openstack_clnt_opts )); then
   typeset -gA _cache_openstack_clnt_opts
   typeset -gA _cache_openstack_clnt_cmds
   typeset -gA _cache_openstack_clnt_cmds_opts
-  typeset -gA _cache_openstack_clnt_cmds_subcmds
-  typeset -gA _cache_openstack_clnt_cmds_subcmd_opts
 fi
 
 local -a conn_opts
@@ -61,65 +59,78 @@ if [[ -n ${clnts_compl_new[(r)$service]} ]]; then
     # Populate caches - clnt_outputs is command raw output used later
     _cache_openstack_clnt_outputs[$service]=${:-"$($service ${(Q)conn_opts} complete 2>/dev/null)"}
     _cache_openstack_clnt_opts[$service]=${${${${(M)${${${${=${(f)"$($service help 2>/dev/null)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.}%--os-}
-    _cache_openstack_clnt_cmds[$service]=${${${${_cache_openstack_clnt_outputs[$service]}/* cmds=\'}/\'*}/complete}
   fi
-  local cmd subcmd
-  # Determine the command
-  for word in ${words:1}; do
-    local s=${_cache_openstack_clnt_cmds[$service]}
-    [[ $s[(wI)$word] -gt 0 ]] && cmd=$word && break
-  done
-  # Populate the subcommand cache
-  if [[ -n $cmd && -z $_cache_openstack_clnt_cmds_subcmds[$service$cmd] ]]; then
-      local t=cmds_${cmd//-/_}
-      _cache_openstack_clnt_cmds_subcmds[$service$cmd]=${${${_cache_openstack_clnt_outputs[$service]}/* $t=\'}/\'*}
+
+  # get worlds left of the curser into an array
+  local -a left_words
+  left_words=(${=LBUFFER})
+
+  # if curser is directly at a word (no space at the end),
+  # exclude the last word to offer right matches
+  # the last word could be a partial match that is later checked (prefix-needed)
+  local partial=""
+  if [[ "${LBUFFER[-1]}" != " " ]]; then
+    partial=${(@)left_words[-1]}
+    left_words=(${(@)left_words[1,$#left_words-1]})
   fi
-  # Determine the subcommand
-  if [[ -n $cmd ]]; then
-    for word in ${words:2}; do
-      local s=${_cache_openstack_clnt_cmds_subcmds[$service$cmd]}
-      [[ $s[(wI)$word] -gt 0 ]] && subcmd=$word && break
-    done
-    # Populate subcommand option cache
-    if [[ -n $subcmd && -z $_cache_openstack_clnt_cmds_subcmd_opts[$service${cmd}--$subcmd] ]]; then
-      local t=cmds_${cmd//-/_}_${subcmd//-/_}
-      _cache_openstack_clnt_cmds_subcmd_opts[$service${cmd}--$subcmd]=${${${_cache_openstack_clnt_outputs[$service]}/* $t=\'}/\'*}
-    fi
+  # remove $service
+  left_words=(${left_words:1})
+
+  # filter out "help"
+  if [[ $left_words[1] == help ]]; then
+    left_words=(${(@)left_words[2,$#left_words]})
   fi
-  # Special treatment for the help command
-  if [[ $cmd == help ]]; then
-      if [[ $words[CURRENT-1] == $cmd && $words[CURRENT] != -* ]]; then
-        # Offer commands
-        [[ -n $_cache_openstack_clnt_cmds[$service] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0
-      elif [[ $words[CURRENT-2] == $cmd && $words[CURRENT-1] != -* && $words[CURRENT] != -* ]]; then
-        # Offer subcommands
-        local cmd=$words[CURRENT-1]
-        local t=cmds_${cmd//-/_}
-        [[ -z $_cache_openstack_clnt_cmds_subcmds[$service$cmd] ]] && _cache_openstack_clnt_cmds_subcmds[$service$cmd]=${${${_cache_openstack_clnt_outputs[$service]}/* $t=\'}/\'*}
-        [[ -n $_cache_openstack_clnt_cmds_subcmds[$service$cmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_subcmds[$service$cmd]} && ret=0
-      else
-        # Handle help<TAB> properly
-        _values -w option help && ret=0
-      fi
-  # Client options
-  elif [[ -z $cmd && $words[CURRENT] == -* ]]; then
-    _values -w option ${(u)=_cache_openstack_clnt_opts[$service]} && ret=0
-  # Commands
-  elif [[ -z $cmd ]]; then
-    if [[ -z $_cache_openstack_clnt_cmds[$service] ]]; then
-      _message "missing authentication options"
+
+  # filter out options (-*)
+  left_words=(${left_words//-*})
+
+  local -a subcmd_array cmds_array cache_key_array cache_values
+  subcmd_array=()
+  cmds_array=(cmds)
+  cache_key_array=(${service})
+  cache_values=()
+  local cache_key cmds
+  cache_key=""
+  cmds=""
+
+  # Check for matches one level at a time
+  # example: "" server create
+  for word in "" ${(@)left_words}; do                   # first loop  second loop        third loop
+    subcmd_array=(${(@)subcmd_array} ${word})           # ()          (server)           (server create)
+    cmds_array=(${(@)cmds_array} ${word})               # (cmds)      (cmds server)      (cmds server create)
+    cmds=${${(j:_:)cmds_array}/-/_}                     #  cmds        cmds_openstack     cmds_server_create
+    cache_key_array=(${(@)cache_key_array} ${word})     # (openstack) (openstack server) (openstack server create)
+    cache_key=${${(j:_:)cache_key_array}/-/_}           #  openstack   openstack_server   openstack_server_create
+
+    # lookup if current word is in cache_values of last elements
+    if [[ ${cache_values[(wI)${word}]} -gt 0 || $word == "" ]]; then
+      _cache_openstack_clnt_cmds[${cache_key}]=${${${_cache_openstack_clnt_outputs[${service}]}/* ${cmds}=\'}/\'*}
     else
-      _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0
+      # unknown word: set cache_key to last cache_key and break
+      cache_key=${${(j:_:)${cache_key_array:0:${#cache_key_array}-1}}/-/_}
+      break
     fi
-  # Subcommands
-  elif [[ -z $subcmd ]]; then
-    [[ -n $_cache_openstack_clnt_cmds_subcmds[$service$cmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_subcmds[$service$cmd]} && ret=0
-  # Subcommand options
+    # set cache_values for next loop
+    cache_values=${_cache_openstack_clnt_cmds[${cache_key}]}
+  done
+
+  # Populate the command cache
+  if [[ -z $_cache_openstack_clnt_cmds[${cache_key}] ]]; then
+    _message "missing authentication options"
   else
-    { ! zstyle -T ":completion:${curcontext}:options" prefix-needed || [[ -prefix - ]] } && \
-      [[ -n $_cache_openstack_clnt_cmds_subcmd_opts[$service${cmd}--$subcmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_subcmd_opts[$service${cmd}--$subcmd]//\:/\\\:} && ret=0
+    # add global options to completion list if current word start with -*
+    local extra_opts
+    if [[ $words[CURRENT] == -* ]]; then;
+      extra_opts=${_cache_openstack_clnt_opts[$service]}
+    fi
+
+    { ! zstyle -T ":completion:${curcontext}:options" prefix-needed \
+          || [[ -n "${partial}" && ${${_cache_openstack_clnt_cmds[${cache_key}]}[(Iw)${partial}*]} -gt 0 || -prefix - ]] } \
+      && _values -w option ${(u)=_cache_openstack_clnt_cmds[${cache_key}]} ${(u)=extra_opts} \
+      && ret=0
   fi
 
+
 # Old style clients
 elif [[ -n ${clnts_compl_old[(r)$service]} ]]; then
   if [[ -z $_cache_openstack_clnt_cmds[$service] ]]; then