各パラメータを異なる方法で自動補完するにはどうすればよいでしょうか?

各パラメータを異なる方法で自動補完するにはどうすればよいでしょうか?

load_pg という関数があり、次のように定義されています。

load_pg () {
    pg_restore --verbose --clean --no-acl --no-owner -h localhost -U $1 -d $2 $3
}

そして、次のコードを使用して、各パラメータを自動補完しようとしています。

#compdef load_pg
_arguments -s \
  "1::_ldpguser" \
  "2::_ldpgdb" \
  "3::_ldpgfile"

_ldpguser () {
  compadd $USER
}

_ldpgdb () {
  compadd $(cat config/database.yml | grep -i database | awk '{print $2}')
}

_ldpgfile () {
  compadd $(ls *.dump*)
}

残念ながら、Tabキーを押しても何も起こりません。何が間違っているのでしょうか?次の回答

答え1

最初のハードル:への引数の構文は空にできませ_argumentsん。メッセージを追加すると、進捗状況がわかります。n:message:actionmessage

_arguments -s \
  "1:username:_ldpguser" \
  "2:database:_ldpgdb" \
  "3:dump file:_ldpgfile"

次のハードルは、補助関数が_arguments実行後に定義されることです。そのため、最初に引数を補完すると、関数の 1 つが存在しないというエラー メッセージが表示されます。関数は使用する前に定義してください。関数の定義を_load_pg明示的にして、自動ロードされたファイルの最後で呼び出す方がよいでしょう。これは不格好に見えますが、zsh に同梱されているほとんどの多機能補完関数はこのように記述されています。

#compdef load_pg

_ldpguser () {
  compadd $USER
}

_ldpgdb () {
  compadd $(cat config/database.yml | grep -i database | awk '{print $2}')
}

_ldpgfile () {
  compadd $(ls *.dump*)
}

_load_pg () {
  _arguments -s \
    "1:user:_ldpguser" \
    "2:database:_ldpgdb" \
    "3:dump file:_ldpgfile"
}

_load_pg "$@"

これで関数の核ができました。次に、個々の関数を整理します。少なくとも次のようになります。

  • compadd $USER意味がないようです。ユーザー名でのみ関数を呼び出したいのであれば、なぜそれを組み込まないのでしょうか? ユーザー名を補完するには、 を呼び出します_users
  • コマンド置換はすべての空白を置換します。行を分割するには、および@を使用します。f パラメータ拡張フラグ. また、grepコマンドをより正確にする必要があり、 と組み合わせることができるかもしれませんgrep
  • compaddからアクションを呼び出すときは_arguments、 のコンテキスト オプションを渡します$expl
  • 補完の説明を記載すると良いでしょう。_describe
  • $(ls *.dump*)*.dump*は、「 、一致するものがない場合、現在のシェルの設定に応じて何かを実行する」と記述する複雑な方法です。出力を解析しないlsええと、いいですか?N グロブ修飾子一致するものがない場合、空のリストを取得することができます。ただし、代わりに_filesこれは、サブディレクトリ内のファイルの補完などの細かい処理を行います。
#compdef load_pg

_ldpgdb () {
  compadd $expl[@] -- "${(@f)$(<config/database.yml grep -i database | awk '{print $2}')}"
}

_load_pg () {
  _arguments -s \
    '1:user:_users' \
    '2:database:_ldpgdb' \
    '3:dump file:_files -g "*.dump*"'
}

_load_pg "$@"

関連情報