ここで私が愚かなことをしている場合は、許してください。ドキュメントが膨大で、検索してもまだ何も見つかりません。
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バージョン)。
質問:
~/.zcompdump
_を読み取って初期補完を設定しますか?_man zshall
_さんのコメント:
次のcompinitの呼び出しでは、完全な初期化を実行する代わりに、ダンプされたファイルを読み取ります。
その場合、compinit
は_~/.zcompdump
_を削除する前に補完を修正しませんでしたか?何か不足していますか?
~/.zcompdump-$(hostname)-5.1.1
とは何ですか、また_.zcompdump
_とどのように関連していますか?唯一の違いは、_~/.oh-my-zsh/completions
_にある1つの補完です(_$ZSH
_が_~/.oh-my-zsh
_を指すため)。ああ、私のzshですか?私はUbuntu 16.04、18.04、19.04をターゲットにしていますが、ディストリビューションに固有でない情報を歓迎します。私はzsh 5.1.1と最近のoh-my-zshを使ってUbuntu 16.04でこれをテストしています。
TL、DR:通常の操作では、ファイルを適切なディレクトリにドロップするだけです。テスト中は、キャッシュファイルを削除する必要があります(デフォルトでは.zcompdump
ですが、ユーザーは別の場所に置くことができ、oh-my-zshは別の場所に置きます)。
簡単な答えは、最初の行が #compdef fab
であるファイルに補完関数を書き込むことです。ファイルは$fpath
のディレクトリにある必要があります。
ファイルには、関数本体、または関数の定義と、それに続く関数の呼び出しを含めることができます。つまり、ファイルには次のようなものが含まれています
#compdef fab
_arguments …
または
#compdef fab
function _fab {
_arguments …
}
_fab "$@"
compinit
を実行する前に、ファイルが$fpath
に存在する必要があります。つまり、.zshrc
の順序に注意する必要があります。最初に$fpath
にカスタムディレクトリを追加してから、compinit
を呼び出します。 oh-my-zshなどのフレームワークを使用する場合は、oh-my-zshコードの前の$fpath
にカスタムディレクトリを追加してください。
compinit
は、補完システムを初期化する関数です。 $fpath
内のすべてのファイルを読み取り、マジックディレクティブ #autoload
および#compdef
の最初の行をチェックします。
.zcompdump
はcompinit
が使用するキャッシュファイルです。 ~/.zcompdump
はデフォルトの場所です。 compinit
を実行するときに別の場所を選択できます。 Oh-my-zshは、-d
オプションを使用してcompinit
を呼び出し、変数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
)行を追加または変更します。その最後のポイントは、テスト中に噛みがちになるものです。 #compdef
行を変更する場合は、.zcompdump
ファイルを削除してzshを再起動する(またはcompinit
を再実行する)必要があります。
補完を再配布可能なパッケージに入れる場合は、補完ファイルをシステム全体の$fpath
にあるディレクトリにドロップするだけです。 Ubuntuパッケージの場合、適切な場所は/usr/share/zsh/vendor-completions
です。 /usr/local
の下にインストールされているものは、/usr/local/share/zsh/site-functions
です。それがあなたがする必要があるすべてです。
透過的ではない1つのことは、アップグレードで#compdef
行を変更する必要がある場合、または一部のファイルを削除または名前変更した場合です。このような場合、ユーザーはキャッシュファイルを削除する必要がありますが、これはマルチユーザーマシンにインストールされたパッケージから実行できることではありません。