Zsh

自定義命令的動態 zsh 自動完成

  • November 14, 2021

我正在嘗試為我編寫的一些自定義函式編寫完成函式,但即使是最基本的函式似乎也很難。

一個範例函式是:

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

這有兩個位置參數,<aws profile name>並且<environment name>

我希望通過執行使完成選項<aws profile name>動態可用 sed -n -E 's/\[([a-zA-Z0-9_\-]+)\]/\1/p' ~/.aws/credentials | tr \\n ' ',並且<environment name>通過執行我呼叫的另一個函式動態提供完成選項eb_names

我發現文件非常稀疏且難以理解。我還看到了類似命令的 zsh-completions repo,但似乎找不到與我需要的類似的東西。

任何幫助入門將不勝感激!

更新

根據@cuonglm 的回答,我使用了:

#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_\-]+)\]/\1/p" ~/.aws/credentials | tr \\n " "))' ;;
             (*) compadd "$@" foo bar
 esac
}

_ebinstances "$@"

我在原始問題中忘記提到的是,我還希望第二個參數的完成取決於第一個參數(兩者都是基於動態執行一些程式碼),例如:

$ eb_instances <cursor>TAB
cuonglm  test

得到我想要的完成。一旦我選擇說第一個,並嘗試自動完成:

$ eb_instances cuonglm <cursor>TAB

我想通過執行來生成完成選項eb_names cuonglm,如果可能的話,還可以深入研究完成,例如,如果正確的候選人是foo-bar

$ eb_instances cuonglm foo<cursor>TAB

我想通過執行生成完成選項eb_names cuonglm foo

乍一看,zsh Completion System似乎很複雜,很難掌握。讓我們嘗試一個例子。

您需要知道的第一件事是zsh完成系統將從$fpath. 確保您的完成目錄出現在:

print -rl -- $fpath

(如果您使用的是oh-my-zsh.oh-my-zsh/completions則在 中$fpath。您可以創建它並將完成功能放在那裡。)

現在,您必須為您的函式創建一個完成文件。它的名稱必須以下劃線 ( _) 加您的函式名稱開頭。在你的情況下,它的名字是_eb_instances.

將這些行添加到_eb_instances文件中:

#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 "$@"

你完成了。保存文件並開始一個新會話以測試完成。你會看到這樣的東西:

$ eb_instances <cursor>TAB
cuonglm  test

$ eb_instances cuonglm <cursor>TAB
dev      prod     staging

您可以閱讀有關_arguments函式和state變數的 zsh 補全系統文件。此外,您將需要更改(cuonglm test)您的sed命令並更改prod staging dev您的eb_names功能。

如果要根據傳遞的第一個參數生成第二個參數,可以使用$words[2]變數:

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

替換echo為您的實際功能。在你的情況下,它是$(eb_names $words[2]).

如果您對此仍有疑問,只需在then 呼叫完成中定義_eb_instances並定義為:eb_instances``.zshrc

compdef _eb_instances eb_instances

您需要使用以下命令初始化完成系統:

autoload -U compinit
compinit

(如果您使用過oh-my-zsh,則已載入)

引用自:https://unix.stackexchange.com/questions/239528