Dynamic Zsh auto-completions

1

I'm trying to write completion functions for some custom functions I wrote, but seem to be really struggling with even the most basic ones.

An example function is:

function eb_instances() {
    if [ "$#" -ne 2 ]; then
        echo "Usage eb_instances <aws profile name> <environment name>"
        echo "e.g.:"
        echo " eb_instances production kraken-prod-api"
        return 1
    fi

    aws ec2 describe-instances --filters  "Name=instance-state-name,Values=running"   "Name=tag:Name,Values=$2" --profile=$1 --output=json | jq -r ".Reservations[].Instances[].PrivateIpAddress"
}

This has two positional arguments, <aws profile name> and <environment name>

I want the completion options for <aws profile name> to be dynamically available by running sed -n -E 's/\[([a-zA-Z0-9_\-]+)\]/\1/p' ~/.aws/credentials | tr \\n ' ', and the completions for <environment name> to be dynamically available by running another function I have called eb_names.

I'm finding the documentation quite sparse and difficult to follow. I've also seen the zsh-completions repo for similar commands but can't seem to find something similar to what I need.

Any help getting started would be much appreciated!

zsquare

Posted 2015-10-29T07:07:41.587

Reputation: 23

Answers

1

I have found zsh completions to be one of the hardest topics in computer science to wrap my brain around. Many failed attempts over many years before I started to get it. The help available online is not great.

For a command that works like floop [ --student=<name> ] <directory> or floop [ -s <name> ] <directory>

#compdef floop

local context state line

_arguments \
  '(--student -s)'{--student=,-s}"[student name to filter on]:student:->students" \
  "*:directory:_files -/"

case $state in
students)
    students=($(echo 'chris pat lynn paige'))
    _describe -t students "a student's name" students && return 0
    ;;
esac

Replace the echo command with a zsh literal array or a command that generates choices for the student option.

The "*:directory:_files -/" line is for the positional argument of a directory path.

There's ways to control if the option can appear more than once or always has to be a separate word (no "=") etc but this example is a pretty simple example.

Mike

Posted 2015-10-29T07:07:41.587

Reputation: 171