Autocompletar zsh dinâmico para comandos personalizados

13

Estou tentando escrever funções de conclusão para algumas funções personalizadas que escrevi, mas parece que estou realmente lutando com as mais básicas.

Uma função de exemplo é:

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"
}

Isso tem dois argumentos posicionais, <aws profile name> e <environment name>

Eu quero que as opções de conclusão de <aws profile name> estejam dinamicamente disponíveis executando sed -n -E 's/\[([a-zA-Z0-9_\-]+)\]//p' ~/.aws/credentials | tr \n ' ' e as conclusões para <environment name> estar dinamicamente disponível executando outra função que chamei de eb_names .

Eu estou achando a documentação bastante esparsa e difícil de seguir. Eu também vi o repositório zsh-completion para comandos semelhantes, mas parece que não consigo encontrar algo semelhante ao que eu preciso.

Qualquer ajuda para começar seria muito apreciada!

Atualizar

Com base na resposta do @ cuonglm , usei:

#compdef ebinstances

_ebinstances() {
  local state

  _arguments \
    '1: :->aws_profile'\
    '*: :->eb_name'

  case $state in
    (aws_profile) _arguments '1:profiles:($(sed -n -E "s/\[([a-zA-Z0-9_\-]+)\]//p" ~/.aws/credentials | tr \n " "))' ;;
              (*) compadd "$@" foo bar
  esac
}

_ebinstances "$@"

O que eu esqueci de mencionar na pergunta original era que eu também queria que a conclusão do segundo argumento fosse dependente do primeiro (ambos com base na execução dinâmica de algum código), por exemplo:

$ eb_instances <cursor>TAB
cuonglm  test

obtém as conclusões que eu quero. Depois que eu selecionar, diga o primeiro e tente concluir automaticamente:

$ eb_instances cuonglm <cursor>TAB

Eu quero gerar as opções de conclusão executando eb_names cuonglm e, se possível, também, detalhamento nas conclusões, por exemplo, se o candidato correto for foo-bar ,

$ eb_instances cuonglm foo<cursor>TAB

Eu quero gerar as opções de conclusão executando eb_names cuonglm foo

    
por zsquare 29.10.2015 / 16:45

1 resposta

14

Na primeira vez, o Sistema de Conclusão do zsh parece ser muito complexo e difícil de entender . Vamos tentar um exemplo.

A primeira coisa que você precisa saber é que zsh completion system carregará as funções de conclusão de $fpath . Verifique se o seu diretório de conclusões aparece em:

print -rl -- $fpath

(Se você usou oh-my-zsh , existe .oh-my-zsh/completions em $fpath , você pode apenas criá-lo e colocar suas funções de conclusão lá)

Agora, você deve criar um arquivo de conclusão para sua função, seu nome deve começar com sublinhado _ , além do nome da sua função. No seu caso, o nome dele é _eb_instances .

Adicione essas linhas a _eb_instances file:

#compdef eb_instances

_eb_instances() {
  local state

  _arguments \
    '1: :->aws_profile'\
    '*: :->eb_name'

  case $state in
    (aws_profile) _arguments '1:profiles:(cuonglm test)' ;;
              (*) compadd "$@" prod staging dev
  esac
}

_eb_instances "$@"

Você terminou. Salve o arquivo e inicie uma nova sessão para testar a conclusão. Você verá algo assim:

$ eb_instances <cursor>TAB
cuonglm  test

$ eb_instances cuonglm <cursor>TAB
dev      prod     staging

Você pode ler a documentação do sistema de conclusão do zsh sobre a função _arguments , state variable. Além disso, você precisa alterar (cuonglm test) com seu comando sed e alterar prod staging dev para sua função eb_names .

Se você quiser gerar o segundo argumento base no qual o primeiro argumento passou, você pode usar $words[2] variable:

case $state in
  (aws_profile) _arguments '1:profiles:(cuonglm test)' ;;
            (*) compadd "$@" $(echo $words[2]) ;;
esac

Substitua echo pela sua função real, no seu caso, é $(eb_names $words[2]) .

Se ainda assim você achar difícil fazer isso, basta definir _eb_instances e eb_instances no seu .zshrc e, em seguida, concluir a chamada como:

compdef _eb_instances eb_instances

Você precisa inicializar o sistema de conclusão com:

autoload -U compinit
compinit

(Se você usou oh-my-zsh , ele foi carregado)

    
por 02.11.2015 / 04:25