From: Christian K <syphdias@gmail.com>
To: Marko Myllynen <myllynen@redhat.com>
Cc: zsh-workers@zsh.org
Subject: Re: OpenStack CLI completion
Date: Fri, 19 Mar 2021 23:05:15 +0100 [thread overview]
Message-ID: <CAJiY44o_cyeKaQGn-kCt3nqOjTSsv9zx6m9hddJphp-+XJVtVQ@mail.gmail.com> (raw)
In-Reply-To: <f2f0d0ed-5262-672e-bee1-ed1018c98617@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 706 bytes --]
> > @Marko, I tried all clients I could find easily and could not find any
> > suggestions including colons. I cannot handle an error I don't know how to
> > throw. Please let me know if you remember an example.
> I think I remember swift and perhaps one or two being somewhat different
> that the rest. But it might be also that it was a client which has since
> then become obsolete. Or perhaps it was added needlessly in the first place.
swift should not be affected since it is in the "swift like" category
and not new style.
> Given that you've tested it with all recent client version I'd say it
> should be safe to drop today.
I'd prefer more testers. :)
I found another small bug and fixed it.
[-- Attachment #2: 0001-Fix-_openstack-completion-for-new-style-clients.patch --]
[-- Type: text/x-patch, Size: 8675 bytes --]
From d408532eb84988d2e565f4b097571b832b8ed172 Mon Sep 17 00:00:00 2001
From: Syphdias <syphdias+git@gmail.com>
Date: Thu, 18 Mar 2021 23:23:16 +0100
Subject: [PATCH] Fix _openstack completion for new style clients
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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
next prev parent reply other threads:[~2021-03-19 22:06 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-07 18:11 Christian K
2021-03-08 15:58 ` Marko Myllynen
2021-03-18 22:45 ` Christian K
2021-03-19 9:37 ` Marko Myllynen
2021-03-19 22:05 ` Christian K [this message]
2021-03-27 16:31 ` Lawrence Velázquez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAJiY44o_cyeKaQGn-kCt3nqOjTSsv9zx6m9hddJphp-+XJVtVQ@mail.gmail.com \
--to=syphdias@gmail.com \
--cc=myllynen@redhat.com \
--cc=zsh-workers@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).