From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19698 invoked by alias); 27 Sep 2016 05:43:54 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 39453 Received: (qmail 16161 invoked from network); 27 Sep 2016 05:43:54 -0000 X-Qmail-Scanner-Diagnostics: from mail-lf0-f49.google.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(209.85.215.49):SA:0(-0.0/5.0):. Processed in 0.675657 secs); 27 Sep 2016 05:43:54 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.1 X-Envelope-From: myllynen@redhat.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _netblocks.google.com designates 209.85.215.49 as permitted sender) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:reply-to:subject:references:to:from:organization :message-id:date:user-agent:mime-version:in-reply-to :content-transfer-encoding; bh=8j14I+kkZNvitje+xoPDX4C2OGaYAZjZei7UO1QXwkg=; b=X36scZtM2McBO/ryAYmeVs654Ta4Djo1molaNaWeZReQZcvu+/JrZ7sB6sq9cAnQAi r6C+nfH9NdOUCmAIoiZqvlJ+Lu1p4pP2SzMdsWwUAqkIYm5HKZ8SDsbzT3DRoxok+Ra2 W1aAWMLf6YmicljC/o5ivYPbjAvWw8lo1RmR1Qv6ujsMdOQLYeCyPCcy35dXhK5Mc0pm gdle+2UMw8JpBZBjrFggu+6FTtXEHyMgAx5pTQI34/8PqcA+dtbqEdmtWWMNyEJHS3wN lgCx9vm/ajRaqlqRkffVn8ruhW7Wa78fd78Vsp1tVPLIzG49bUEm0pX8+nAwm+Jxlumk hRxg== X-Gm-Message-State: AA6/9Rlz03JR3rU3ZEHfj2ZoDjkdgqt7uynFzbUmuQQXXEu8qOzU/rem6lpQP0SLr7+EbuYW X-Received: by 10.28.126.81 with SMTP id z78mr1203324wmc.13.1474955022552; Mon, 26 Sep 2016 22:43:42 -0700 (PDT) Reply-To: Marko Myllynen Subject: Re: Zsh OpenStack completions References: <9361ff20-f0f2-9acd-e43e-4b1e2e203531@redhat.com> <20160906233751.GA17896@fujitsu.shahaf.local2> <0bbb2428-19f0-4741-10c5-b0c79f9df905@redhat.com> To: zsh workers From: Marko Myllynen Organization: Red Hat Message-ID: <41b24ccb-9526-4cf6-7755-a125929529f7@redhat.com> Date: Tue, 27 Sep 2016 08:43:39 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0 MIME-Version: 1.0 In-Reply-To: <0bbb2428-19f0-4741-10c5-b0c79f9df905@redhat.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Hi, On 2016-09-19 09:24, Marko Myllynen wrote: > On 2016-09-09 09:38, Marko Myllynen wrote: >> On 2016-09-07 12:31, Marko Myllynen wrote: >>> >>> I updated the patch quickly to address some of your comments but based >>> on Eric's reply it sounds like we also need to discuss should we >>> include these completions in zsh upstream in the first place. >> >> Here's an updated patch based on initial review comments from Daniel, >> most notably more comments added. > > There were not further comments on this, how should we proceed? I think > the lower level technical aspects should be pretty much ok now but does > this look like something that would be appropriate for zsh upstream? Below is an updated patch which, based on Oliver's suggestion, makes the subcommand option completion conditional based on: { ! zstyle -T ":completion:${curcontext}:options" prefix-needed || [[ -prefix - ]] } --- Completion/Unix/Command/_openstack | 192 +++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 Completion/Unix/Command/_openstack diff --git a/Completion/Unix/Command/_openstack b/Completion/Unix/Command/_openstack new file mode 100644 index 0000000..39fa30c --- /dev/null +++ b/Completion/Unix/Command/_openstack @@ -0,0 +1,192 @@ +#compdef openstack aodh barbican ceilometer cinder cloudkitty designate glance gnocchi heat ironic keystone magnum manila mistral monasca murano neutron nova sahara senlin swift trove + +# https://wiki.openstack.org/wiki/OpenStackClients +# http://docs.openstack.org/user-guide/common/cli-install-openstack-command-line-clients.html + +local curcontext="$curcontext" state line expl ret=1 + +local -a clnts_compl_new clnts_compl_old clnts_swift_like + +# +# We support three different client categories: +# 1) Clients with new style complete command where output is like: +# +# cmds='alarm alarm-history capabilities complete help' +# cmds_alarm='create delete list show update' +# cmds_alarm_history='search show' +# cmds_alarm_history_search='-h --help -f --format -c --column --max-width --noindent --quote --query' +# +# 2) Clients with old style bash-completion command which does +# not separate options and commands: +# +# --tenant_id floatingip-delete bgp-peer-delete --default-prefixlen net-create [...] +# +# 3) Swift, slightly different from 2) +# +clnts_compl_new=( aodh barbican designate gnocchi openstack ) +clnts_compl_old=( ceilometer cinder cloudkitty glance heat ironic keystone magnum manila mistral monasca murano neutron nova sahara senlin trove ) +clnts_swift_like=( swift ) + +# Python clients take quite some time to start up and some (openstack(1)) +# even go over the network for completions so we cache things pretty hard +if (( ! $+_cache_openstack_clnt_opts )); then + typeset -gA _cache_openstack_clnt_outputs + 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 +local opt arg word +# Only openstack(1) requires parameters to provide completion info +if [[ $service == openstack && -n ${words[(r)--os-*]} ]]; then + if (( ! $+_cache_openstack_conn_opts )); then + _cache_openstack_conn_opts=( ${(M)${=${(f)"$($service help 2>/dev/null)"}}:#--os-*} ) + fi + # --os-tenant-id --os-tenant-name are deprecated but still widely used + for opt in ${=_cache_openstack_conn_opts} --os-tenant-id --os-tenant-name; do + arg= + for word in ${words:1}; do + [[ $word == $opt ]] && arg=$word && break + done + [[ -n $arg && -n ${arg##-*} ]] && conn_opts=( $conn_opts $opt $arg ) + done +fi + +# New style clients +if [[ -n ${clnts_compl_new[(r)$service]} ]]; then + if [[ -z $_cache_openstack_clnt_cmds[$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=\'}/\'*} + 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 + 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 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" + else + _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0 + 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 + 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 + fi + +# Old style clients +elif [[ -n ${clnts_compl_old[(r)$service]} ]]; then + if [[ -z $_cache_openstack_clnt_cmds[$service] ]]; then + # Populate caches + _cache_openstack_clnt_opts[$service]=${${${(M)${${${${=${(f)"$($service help 2>/dev/null)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.} + _cache_openstack_clnt_cmds[$service]=${${(M)${=${(f)"$($service bash-completion 2>/dev/null)"}}:#[A-Za-z]*}/bash-completion} + fi + local cmd + # 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 command option cache + # Mostly no options for help, prevent consecutive calls with help here + if [[ -n $cmd && $cmd != help && -z $_cache_openstack_clnt_cmds_opts[$service$cmd] ]]; then + _cache_openstack_clnt_cmds_opts[$service$cmd]=${${${(M)${${${${=${(f)"$($service help $cmd 2>/dev/null)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.} + fi + # Special treatment for the help command + if [[ $cmd == help ]]; then + if [[ $words[CURRENT-1] == help && $words[CURRENT] != -* ]]; then + _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0 + else + _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 + _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0 + # Command options + else + { ! zstyle -T ":completion:${curcontext}:options" prefix-needed || [[ -prefix - ]] } && \ + [[ -n $_cache_openstack_clnt_cmds_opts[$service$cmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_opts[$service$cmd]//\:/\\\:} && ret=0 + fi + +# Swift like clients +elif [[ -n ${clnts_swift_like[(r)$service]} ]]; then + if [[ -z $_cache_openstack_clnt_cmds[$service] ]]; then + # Populate caches - clnt_outputs is command raw output used later + _cache_openstack_clnt_outputs[$service]=${(f)"$($service --help 2>/dev/null)"} + _cache_openstack_clnt_opts[$service]=${${${${(M)${${${${=_cache_openstack_clnt_outputs[$service]}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.}/=*} + _cache_openstack_clnt_cmds[$service]=${=${(M)${(M)${(f)_cache_openstack_clnt_outputs[$service]}:# [a-z]*}/ [A-Z]*}} + fi + local cmd + # 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 command option cache + if [[ -n $cmd && -z $_cache_openstack_clnt_cmds_opts[$service$cmd] ]]; then + _cache_openstack_clnt_cmds_opts[$service$cmd]=${${${(M)${${${${=${(f)"$($service $cmd --help 2>/dev/null)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.} + fi + # Client options + if [[ -z $cmd && $words[CURRENT] == -* ]]; then + _values -w option ${(u)=_cache_openstack_clnt_opts[$service]} && ret=0 + # Commands + elif [[ -z $cmd ]]; then + _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0 + # Command options + else + { ! zstyle -T ":completion:${curcontext}:options" prefix-needed || [[ -prefix - ]] } && \ + [[ -n $_cache_openstack_clnt_cmds_opts[$service$cmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_opts[$service$cmd]//\:/\\\:} && ret=0 + fi + +fi + +return ret Thanks, -- Marko Myllynen