zshコンプリート機能を少し拡張したいです。
関数全体の本文を私のホームディレクトリに入れることを避け、1行だけ変更したいと思います。代わりに、呼び出しを傍受して元の関数を直接呼び出したいと思います。ベアコードから:
<make sure _the_original_function is loaded>
_backup_of_original_function=_the_original_function
_the_original_function() {
_arguments "-superduper[that one option I always need]"
_backup_of_originial_function $@
}
私の場合、ほぼすべてのプロジェクトにcmakeプロパティがあるので、cmakeの完成を修正したいと思います。完了時にこのオプションがないと、オプションではなくプロジェクトにこのオプションがあるよりも迷惑になります。そのため、_cmake
どこかにコピーせずに_cmake_define_common_property_names()
自分の場所にコピーします.zshrc
。
_cmake_define_common_property_names() {
local properties; properties=(
'MY_GREAT_OPTION:be awesome'
)
_describe -t 'my-property-names' 'my property name' properties $@
**call original _cmake_define_common_property_names here
}
だから欠けているのは、_cmake_define_common_property_names
新しい関数名をロードして割り当てることです。
~からここ頑張った
autoload -Uz +X _cmake_define_common_property_names
ただし、これは失敗します(関数は独自のファイルに定義されていませんが)_cmake
。
注:元のバージョンで関数が呼び出された場所を変更する必要がないように、新しい関数名を指定しませんでした。
部分的には yes 動作しますautoload -Uz +X _cmake
が、これは_cmake
ロードされたものだけを確認します(を呼び出して確認しましたfunctions _cmake
)。ヘルパー関数をロードしません_cmake_define_common_property_names
。
だから私の2つの質問は
$fpath
ファイルから関数をロードする方法- 一度関数をロードします。これをスクリプトにコピーしたり、新しい関数名を割り当てるにはどうすればよいですか?
答え1
機能をパッチする方法
関数のコードは連想配列に格納されますfunctions
。以下は、正規化されたスペースがあり、コメントがないソースコードです(zshが語彙分析を実行し、マークアップを見やすく印刷しました)。配列の項目を変更して関数のコードを変更できますfunctions
。たとえば、始めにコードを追加するには、次のようにします。
functions[_cmake_define_common_property_names]="
… # your extra code here
$functions[_cmake_define_common_property_names]"
変更したいものが単に元のコードの前後のコードの実行に関連する場合(またはより一般的には条件に入れるなど)、関数を新しい名前にコピーしてその新しい名前を呼び出すように関数をオーバーライドできます。 zsh 5.8 以降、次のコマンドを使用して簡単にこれを行うことができます。functions -c
。
functions -c _cmake_define_common_property_names _cmake_define_common_property_names_orig
_cmake_define_common_property_names () {
…
_cmake_define_common_property_names_orig "$@"
}
あるいは、すべてのzshバージョンで配列を使用してfunctions
関数を別の名前にコピーすることもできます。
functions[_cmake_define_common_property_names_orig]=$functions[_cmake_define_common_property_names]
_cmake_define_common_property_names () {
…
_cmake_define_common_property_names_orig "$@"
}
すべての機能をロード
自動ロードファイルからすべての機能をロードする信頼できる唯一の方法は、機能を実行することです(副作用なしに機能を実行する準備ができている場合)。完了関数の場合、関数を実行してエラーをビットバケットにリダイレクトするだけです。完了コンテキストで実行されていないと文句を言い、何もしません。
_cmake 2>/dev/null
# Now _cmake_xxx is defined
autoload -Uz +X _cmake
うまくいかないのは、ヘルパー関数が関数_cmake
自体に定義されているからです。
% echo $functions[_cmake]
builtin autoload -XU
% autoload -Uz +X _cmake
% echo $functions[_cmake]
…
(( $+functions[_cmake_define_property_names] )) || _cmake_define_property_names () {
…
}
…
local cmake_command_actions
cmake_command_actions=('-E[CMake command mode]:*:command')
_cmake_command () {
_arguments -C -s - command "$cmake_command_actions[@]"
}
local cmake_suggest_build
cmake_suggest_build=('--build[build]')
if [ $CURRENT -eq 2 ]
then
_arguments -C -s - help "$cmake_help_actions[@]" - command "$cmake_command_actions[@]" - build_opts "$cmake_build_options[@]" - build_cmds "$cmake_suggest_build[@]" && return 0
elif [[ $words[2] = --help* ]]
then
_cmake_help
elif [[ $words[2] != -E ]]
then
_cmake_on_build
else
_cmake_command
fi
トップレベルの機能を実際に実行したくない場合は、いくつかのオプションがあります。
_cmake_define_common_property_names
定義内の定義をパッチします_cmake
。_cmake_define_common_property_names
の定義から定義を抽出し_cmake
、それを使用して_cmake_define_common_property_names_orig
またはを定義します_cmake_define_common_property_names
。_cmake
関数定義以外の部分を削除するには、定義をパッチして実行します。実際にはうまくいきませんが、より良い_cmake
仕事をする他の構造があります。たとえば、_cvs
純粋に条件付き関数定義(例(( $+functions[_cvs_command] )) || _cvs_command () { … }
:)、タイトル関数定義、最後にタイトル関数呼び出しで構成されているため、すべての関数を定義できますが、何もできません。最後の行を削除することによって。autoload -Uz +X _cvs functions[_cvs]=${functions_cvs%'$\n'*} _cvs # Patch auxiliary functions here