3

I am trying to create a completion where one of my completions will be dynamically generated depending on the values of the other flags. For example

local state

_arguments \
  '-f[fabric]:fabric:->fabrics' \
  '-c[containers/application where log resides]:container:->containers' \
  '-l[name of log file]:log:->logs'

case "$state" in
    (fabrics)
        _values 'fabrics' \
          'fab1' \
          'fab2'
    ;;
(containers)
    _values 'containers' \
      'container1' \
      'container2'
    ;;
(logs)
    # show A B C if "-c container1" was entered
    # show D E F if "-c container2" was entered
    # show G if "-c" was not provided yet
esac

I am having trouble getting the "-l" flag to be dynamically generated.

diablo1234
  • 379
  • 2
  • 3
  • 10

1 Answers1

3

We could inspect the $words:

Completion Special Parameters
...
Inside completion widgets, and any functions called from them, some parameters have special meaning;
...
words
This array contains the words present on the command line currently being edited.

-- zshcompwid(1): Completion Special Parameters, Completion Widgets

We could do the stuff like this:

(logs)
    local -i index=${words[(I)-c]}
    local -i ret=0
    if ((index == 0)); then
        _values 'logs' F
        ret=$?
    elif [[ "$words[index+1]" == container1 ]]; then
        _values 'logs' A B C
        ret=$?
    elif [[ "$words[index+1]" == container2 ]]; then
        _values 'logs' D E F
        ret=$?
    fi
    return ret

To inspect arrays, it is usefull to use the array Subscript Flags:

Subscript Flags
If the opening bracket, or the comma in a range, in any subscript expression is directly followed by an opening parenthesis, the string up to the matching closing one is considered to be a list of flags, as in name[(flags)exp].

-- zshparam(1), Subscript Flags, Array Subscripts, Array Parameters

So,$words[(I)-c] means I "flag" + -c as "exp" for $words which is "Last matching element's index for "-c" in the array $word". For example:

 $ tmp=(my-test-command -f flag -c container1 -l)
 $ echo $tmp[(I)-c]
 4
 $ echo $tmp[(I)container1]
 5
 $ tmp=(my-test-command -f flag -c container1 -c container2 -l)
 $ echo $tmp[(I)-c]
 6
hchbaw
  • 4,894
  • 18
  • 16
  • This is great! I got it working, but I don't quite understand the first index part. Can you explain what (I) and -c is? – diablo1234 Sep 20 '17 at 07:54
  • 1
    Updated; I've added some example/usage for inspecting arrays with subscript flags. – hchbaw Sep 20 '17 at 08:21