更新履歴
- : 公開
バージョン情報
- Composer: 2.7.4
- PHP: 8.3.6
- Zsh: 5.9
はじめに
Composer は PHP のデファクトスタンダードなパッケージマネージャである。 Zsh では、composer
コマンドに対する補完が提供されており、composer
と入力してタブキーを押すと、利用可能なコマンドやオプションが補完される。 Zsh の補完はシェル関数の形で実装されており、composer
コマンドに対応した補完をおこなうのは _composer
である。 記事執筆時点での補完関数の定義は、GitHub のミラーリポジトリから参照できる。
発生していた問題
composer
コマンドはカスタムコマンド (composer.json
の scripts
で定義されたコマンド) に対して補完をおこなわない。 つまり、途中まで入力されたカスタムコマンドを補完しないし、カスタムコマンドの引数も補完しない。 例えば、PHPUnit を呼び出す phpunit
というカスタムコマンドを定義し composer phpu
まで打ってタブキーを押しても、composer phpunit
にはならない。 また、composer phpunit -- --
まで打ってタブキーを押しても、phpunit
コマンドのオプションは補完されない。
このことは、先ほどリンクを載せた _composer
関数を定義しているファイルの冒頭にも書かれている。
# - @todo We don't complete custom commands (including script aliases). This is
# easy to do in the general case, but it probably requires some clever caching
# to avoid introducing a noticeable lag to every completion operation, due to
# the way command resolution works and the fact that discovering custom
# commands requires making slow calls to Composer
やりたいこと
確かに、カスタムコマンドに対して完全な補完を提供するのは不可能か、あるいは実現できても遅くなりすぎるだろう。 しかし、不完全なフォールバックを提供するくらいなら可能なはずだ。
この記事では、これらのカスタムコマンドについて、Zsh が提供するデフォルトのファイル・ディレクトリ補完を適用する。 つまり、composer phpunit -- tests/
まで打ってタブキーを押すと、tests
ディレクトリの下にあるテストファイルまたはディレクトリが補完される。
解決策
まずは、Zsh で補完関数を提供する場合のボイラープレートコードを書く。 以下は ~/.zshrc
にすべて書く前提だが、autoload
を設定するなどすれば別ファイルに分離できる (詳細な手順は割愛)。
compdef _my_composer composer composer.phar
compdef
は Zsh が用意している関数で、第一引数に補完関数の名前、第二引数以降に補完を適用するコマンド名を並べる。 この場合は、composer
コマンドや composer.phar
コマンドに対して _my_composer
を使って補完をおこなうよう定義している。
次に _my_composer
を定義する。基本的にはデフォルトの composer
コマンドの補完関数 (つまり _composer
関数) を使い、それが何も返さなかった場合に限り、Zsh のファイル・ディレクトリ補完へフォールバックする。
function _my_composer() {
_composer "$@" || _files "$@"
}
_composer
コマンドは何も補完候補がなかったとき非ゼロな exit status で終了するので、そうであったなら _files
を呼び出す。 _files
は、Zsh がデフォルトで用意しているファイル・ディレクトリの補完をおこなう関数である。
まとめ
これらの設定をおこなうことで、部分的ながら Composer のカスタムコマンドに対して補完をおこなうことができる。 特に、PHPUnit や PHPStan などの対象ファイル・ディレクトリを引数に取るようなコマンドを使う場合に有用であろう。