カスタムzshを「ただ動作する」ように正しく作成する方法は?

カスタムzshを「ただ動作する」ように正しく作成する方法は?

私がここで愚かなことをしたならば、許してください。ドキュメントは膨大で検索してもまだ何も出ていません。

というカスタムスクリプトのシェル補完機能を作成しようとしていますfab。 bashを使うと簡単です。ただ入れるだけでうまく/etc/bash_completion.dいきます。しかし、マブソサ、zshはPITAですか?

完成機能がありますが、_fab有効になると正常に動作しますcompdef _fab fab/usr/share/zsh/vendor-completions/_fabすでに私に配置しました$fpath。ファイルはで始まり、#compdef fabで終わりますcompdef _fab fab。よさそうだ:

$ type _fab
_fab is an autoload shell function

しかし、新しいシェルを起動するたびにfab完成は機能しません(vendor-completionsたとえば、他の機能は_docker問題ありません)。compinitこの特定のシェルの問題を解決しました。私はそれがrm ~/.zcompdump ~/.zcompdump-$(hostname)-5.1.1; compinit永久に動作することがわかりました(5.1.1 =私のzshバージョン)。

質問:

  1. ~/.zcompdump初期完了を設定するためにいつ、何を読むべきですか?
  2. man zshall説明する:

    次のcompinit呼び出しは、完全な初期化を実行するのではなく、ダンプされたファイルを読み取ります。

    それでは、compinit削除する前に完成度は修正されませ~/.zcompdumpん。私は何を逃したことがありませんか?

  3. それは何とどの~/.zcompdump-$(hostname)-5.1.1ように関連していますか.zcompdump?唯一の違いは、完了の1つ~/.oh-my-zsh/completions$ZSHを指すので~/.oh-my-zsh)が完了の1つであることです。これはoh-my-zshの仕事ですか?
  4. これらの補完エントリを再頒布可能パッケージにパッケージ化したり、インストーラスクリプトを生成したい場合は、zsh補完エントリをどこに配置する必要がありますか?すべてが正しく機能していることを確認するには、インストール中に何をすべきですか?

Ubuntu 16.04、18.04、19.04を対象としていますが、distro関連情報ではない場合は大歓迎です。私はzsh 5.1.1と最近oh-my-zshを使ってUbuntu 16.04でテストしています。

答え1

TL、DR:通常の作業では、ファイルをそのディレクトリに配置するだけです。テスト時にキャッシュファイルを削除する必要があります(.zcompdumpデフォルトでは、ユーザーは別の場所に保存できますが、oh-my-zshは別の場所に保存します)。


簡単な答えは、最初の行を持つファイルに完成関数を書くことです。#compdef fab。ファイルはのディレクトリになければなりません$fpath

ファイルには関数本体を含めることもできますし、関数定義と関数呼び出しを含めることもできます。つまり、ファイルには次の内容が含まれています。

#compdef fab
_arguments …

または

#compdef fab
function _fab {
  _arguments …
}
_fab "$@"

$fpathこのファイルは実行する前に存在する必要がありますcompinit。これは順序に注意を払う必要があることを意味します.zshrc。まず、カスタムディレクトリを追加して$fpathから呼び出しますcompinit。 oh-my-zshなどのフレームワークを使用している場合は、$fpathoh-my-zshコードの前にカスタムディレクトリを追加する必要があります。

compinitシステムを初期化して完了する機能です。すべてのファイルを読み、$fpath最初の行に魔法のコマンドがあることを確認してください。#autoloadそして#compdef

.zcompdumpデフォルトの場所です。実行時に別の場所compinit~/.zcompdump選択できますcompinit。 Oh-my-zshを呼び出すcompinitときに、-d変数によって提供される他のキャッシュファイル名を使用することを選択できますZSH_COMPDUMPデフォルトは

ZSH_COMPDUMP="${ZDOTDIR:-${HOME}}/.zcompdump-${SHORT_HOST}-${ZSH_VERSION}"

ホスト名は、コンピュータ間でホームディレクトリが共有され、異なるコンピュータに異なるソフトウェアがインストールされているユーザーのために含まれます。キャッシュファイルがバージョン間互換性がないため、zshバージョンが含まれています(バージョンごとに異なるコードが含まれています)。

あなたのすべての問題は古いキャッシュファイルによって引き起こされると思います(これは状況が複雑すぎます)。残念ながら、キャッシュされたファイルが古いかどうかを確認するZshアルゴリズム完璧ではありません。おそらくスピードのためです。ファイルの内容やタイムスタンプを確認せずに数だけ$fpathカウントします。ファイルは.zcompdump次の行で始まります。

#files: 858     version: 5.1.1

zshバージョンとファイル数が正しい場合、zshはキャッシュされたファイルをロードします。

キャッシュファイルには、完了機能へのコードではなくコマンド名間の接続のみが含まれます。キャッシュの透明性が機能するいくつかの一般的なシナリオは次のとおりです。

  • 新しいファイルが追加されると、$fpathキャッシュは無効になります。
  • より一般的には、ファイルを追加および削除し、$fpath削除されたファイルの総数が削除されたファイルの総数と異なる場合、キャッシュは無効になります。
  • 名前を変更せずにファイルを別のディレクトリに移動すると、キャッシュ内の$fpathどのエントリにも影響しないため、キャッシュは正しく保持されます。
  • 最初の行を変更せずにファイルを変更すると、キャッシュ内の$fpathどのエントリにも影響を与えないため、キャッシュは正しいままです。

キャッシュが無効になっているがzshがそれを認識しないいくつかの一般的なシナリオは次のとおりです。

  • いくつかのファイルを追加し$fpath、まったく同じ数のファイルを削除します。
  • ファイル名を$fpath
  • #compdefファイルの上部に(または)行を追加または変更できます。#autoload

この最後のポイントは、テスト中に最も難しい問題です。この行を変更した場合は、ファイルを削除してzshを再起動(または再実行)#compdefする必要があります。.zcompdumpcompinit

再頒布可能パッケージに完成ファイルを挿入する場合は、完成ファイルをシステム全体のディレクトリに配置するだけです$fpath。 Ubuntuパッケージ/usr/share/zsh/vendor-completionsの場合、適切な場所はです/usr/local/usr/local/share/zsh/site-functionsそれはあなたがしなければならないすべてです。

透明でないことの1つは、#compdefアップグレードで行を変更する必要があるか、特定のファイルを削除するか名前を変更する必要があるかです。この場合、ユーザーはキャッシュファイルを削除する必要があります。これは、マルチユーザーコンピュータにインストールされているパッケージでは実行できない操作です。

関連情報