From 5d0bb152ef1486e1b38326e37e91e98295bc6946 Mon Sep 17 00:00:00 2001 From: Syphdias Date: Thu, 18 Mar 2021 23:23:16 +0100 Subject: 48192: Fix _openstack completion for new style clients --- ChangeLog | 3 + Completion/Unix/Command/_openstack | 117 ++++++++++++++++++++----------------- 2 files changed, 67 insertions(+), 53 deletions(-) diff --git a/ChangeLog b/ChangeLog index 204a71296..e8be1f36d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-03-31 Oliver Kiddle + * Christian K: 48192: Completion/Unix/Command/_openstack: + Fix openstack completion for new style clients + * Marc Chantreux: users/26557: Completion/Unix/Command/_surfraw: add bookmarks support and remove the header from the final list 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 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 -- cgit 1.4.1