Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] Fix _openstack completion for new style clients
- X-seq: zsh-workers 48228
- From: Syphdias <syphdias+git@xxxxxxxxx>
- To: zsh-workers@xxxxxxx
- Cc: Syphdias <syphdias+git@xxxxxxxxx>
- Subject: [PATCH] Fix _openstack completion for new style clients
- Date: Tue, 23 Mar 2021 09:56:39 +0100
- Archived-at: <https://zsh.org/workers/48228>
- Archived-at: <http://www.zsh.org/sympa/arcsearch_id/zsh-workers/2021-03/20210323085639.29974-1-syphdias%2Bgit%40gmail.com>
- List-id: <zsh-workers.zsh.org>
I have rewritten the completion function for new style clients. It no longer
differentiates between command and sub command since this lead to a limited
depth for completion lookups. This gets rid of the extra global caching variable
`_cache_openstack_clnt_cmds`. I tried to stay true to the prefix-needed
setting.
First I process the words left of the cursor. `words` did not provide this
granularity I needed so I opted to parse `LBUFFER` also for saving a partial
input/match for later. I remove `help` since everything after it is normal (sub)
command, so matches are identical to proper commands. Also I filter out every
flag/option.
To find the proper completion options I try one level at a time.
* $service
* $service $some_command
* $service $some_command $some_command_for_some_command
* etc.
You could probably do this in reverse to save time but I don't think it is worth
the effort.
I add the global options if `-` is used as a prefix at the current position.
Caveats:
* I know there are options like `--file`. The new implementation does not handle
this – neither did the old one. For this level, I'd suggest the OpenStack team
to provide official zsh completions
* Ignores everything right of the cursor so you can end up with command
suggestion that are already on the right
* `openstack complete` gets completed now, old implementation ignored it
---
Completion/Unix/Command/_openstack | 117 ++++++++++++++++-------------
1 file 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
--
2.30.1
Messages sorted by:
Reverse Date,
Date,
Thread,
Author