usr_52.txt For Vim バージョン 9.1. Last change: 2024 Oct 07
VIM USER MANUAL - by Bram Moolenaar
大きなプラグインを作る
プラグインが単純なこと以上のことを行うと、大きくなる傾向があります。このファイ
ルは、それらが高速に読み込まれるようにする方法と、それらを小さなパーツに分割す
る方法を説明しています。
52.1 エクスポートとインポート
52.2 オートロード
52.3 インポート/エクスポートなしのオートロード
52.4 他に使えるメカニズム
52.5 旧来のスクリプトから Vim9 script を使う
52.6 Vim9 サンプル: comment および highlight-yank プラグイン
次章: usr_90.txt Vim のインストール
前章: usr_51.txt プラグインを作る
目次: usr_toc.txt
==============================================================================
52.1 エクスポートとインポート
Vim9 script は大きな Vim script を容易に書けるようにデザインされています。他の
スクリプト言語、特に TypeScript のようになっています。また、処理内の関数はコン
パイルされ素早く実行できます。これにより Vim9 script はとても速く、最大100倍に
なります。
基本的な考え方は、スクリプトファイルには、スクリプトファイル内でのみ使用される
プライベートな項目と、それらをインポートするスクリプトで使用できるエクスポート
される項目があるということです。これにより、何がどこで定義されているかが非常に
明確になります。
1つの関数をエクスポートし、1つのプライベート関数を持つスクリプトの例から始めま
しょう:
export は Vim9 script でのみ動くので vim9script コマンドが必要です。
export def GetMessage(... の行は export から始まっていて、この関数が他のス
クリプトから呼び出すことができることを意味します。def GetReply(... の行は
export で始まっておらず、これはスクリプトローカル関数であり、このスクリプト
ファイル内でのみ使用できます。
次にインポートされるスクリプトについて説明します。この例の中ではこの配置を使用
しており、これは "pack" ディレクトリ下のプラグインに適しています:
.../plugin/theplugin.vim
.../lib/getmessage.vim
"..." ディレクトリが 'runtimepath' に追加されていると仮定すると、Vim は
"plugin" ディレクトリからプラグインを探し "theplugin.vim" を読み込みます。Vim
は "lib" ディレクトリを認識しません、そこに任意のスクリプトを置くことができま
す。
上の GetMessage() をエクスポートしているスクリプトは lib/getmessage.vim 内に
あります。GetMessage() 関数は plugin/theplugin.vim 内にて使用されます:
import コマンドは "../" で始まる相対パスを使用しています。これは、1つ上のディ
レクトリに移動することを意味します。他の種類のパスについては、:import コマン
ドを参照してください。
プラグインが提供するコマンドを試す方法:
関数 GetMessage() には、インポートしたスクリプト名 "getmessage" がプリフィック
スとして付けられていることに注意してください。こうすることで、使用されるすべて
のインポートされた関数について、それがどのスクリプトからインポートされたかが分
かります。複数のスクリプトをインポートする場合、それぞれで GetMessage() 関数を
定義できます:
インポートしたスクリプトの名前が長いあるいは色々な箇所で使う場合、引数に "as"
を追加することで短くできます:
再読み込み
1つ覚えておくべきこと: インポートされた "lib/getmessage.vim" スクリプトは1度だ
け読み込まれます。インポート済みで2度目に読み込む時はスキップされ、項目は最初
に作成された以降そのままです。これはインポートコマンドが他のスクリプト内にあ
るか、再読み込みされた同じスクリプト内にあるかは関係ありません。
これはプラグインを使用する場合は効率的ですが、プラグインを開発中の場合は、イン
ポート後に "lib/getmessage.vim" を変更しても効果がありません。Vim を終了し、再
起動する必要があります。(理論的根拠: スクリプトで定義された項目は、コンパイル
された関数で使用できます。スクリプトを再度読み込むと、これらの関数が壊れる可能
性があります)。
グローバルの使用
時には、グローバル変数や関数を使用して、どこでも使えるようにしたい場合がありま
す。プラグインに設定を渡すグローバル変数がその良い例です。他のスクリプトが同じ
名前を使うのを避けるために、他の場所で使われる可能性が非常に低いプリフィックス
を使用します。例えば、"mytags" プラグインがある場合、次のように使用します:
==============================================================================
52.2 オートロード
大きなスクリプトを分割しても、スクリプトが使用された瞬間にすべての行がロードさ
れ、実行されます。import するたびに、インポートしたスクリプトをロードして、
そこで定義されている項目を探します。これはエラーを早期に発見するためには良いこ
とですが、同時に時間もかかります。そのため、その機能があまり使用されない場合
は、無駄な時間がかかってしまいます。
import でスクリプトをすぐにロードするのではなく、必要になるまで延期すること
ができます。上記の例を使用すると、plugin/theplugin.vim スクリプトで行う必要が
ある変更は1箇所だけです:
スクリプトの残りの部分は何も変更する必要はありません。ただし、型はチェックされ
ません。GetMessage() 関数が使用されるまで、その存在すらチェックされません。ス
クリプトにとってどちらがより重要かを決定する必要があります: 高速な起動か早期に
エラーが分かるか。すべての動作を確認した後で、"autoload" 引数を追加することも
できます。
オートロードディレクトリ
もう1つの形式は絶対パスでも相対パスでもないスクリプト名で autoload を使用する
ことです:
これはスクリプト "monthlib.vim" を 'runtimepath' のオートロードディレクトリの
中から検索します。Unix では、ディレクトリの1つが "~/.vim/autoload" であること
が多いです。これはまた 'packpath' の、その下の "start" からも検索します。
この方法の主要な利点として、このスクリプトを他のスクリプトと共有するのが容易で
あることです。Vim が 'runtimepath' 内の "autoload" ディレクトリから検索するた
め、スクリプト名は一意である必要があり、プラグインはいくつかのプラグインマネー
ジャーとともに利用される場合では、'runtimepath' にディレクトリを追加されること
があり、それぞれが "autoload" ディレクトリを持っているためです。
オートロードなしは:
Vim は 'runtimepath' のインポートディレクトリ内からスクリプト "monthlib.vim"
を検索します。Note この場合、"autoload" を追加または削除すると、スクリプトが見
つかる場所が変わります。相対パスまたは絶対パスでは、場所は変わりません。
==============================================================================
52.3 インポート/エクスポートなしのオートロード
write-library-script
インポート/エクスポート以前のメカニズムは依然として使用でき一部ユーザーは多少
単純であると感じるかもしれません。それは特別な名前によって関数を呼び出すという
アイデアです。その関数はオートロードスクリプト内にあります。そのスクリプトのこ
とをライブラリスクリプトと呼びます。
オートロードのメカニズムは、関数名が "#" 文字を含んでいることが前提となってい
ます:
Vim は埋め込まれた "#" 文字によって関数名を認識し、まだ定義されていない場合は
"autoload/mylib.vim" というスクリプトを 'runtimepath' から探します。そのスクリ
プトは "mylib#myfunction()" 関数を定義している必要があります。言うまでもなく、
"mylib" という名前は "#" の前の部分であり、".vim" を追加してスクリプト名として
使用されます。
mylib.vim スクリプト内に他の多くの関数を置ことができ、ライブラリスクリプト内の
構成は自由です。ただし、'#' の前部分がスクリプト名に一致する関数名を使用する必
要があります。そうしないと、Vim はロードするスクリプトを認識できません。この点
がインポート/エクスポートのメカニズムとの違いになります。
本当に夢中になり多数のライブラリスクリプトを書くのであれば、サブディレクトリを
使用したいでしょう。例:
ここでは、スクリプト名は、関数名から最後の "#" までが取得されます。途中の "#"
はスラッシュで置き換えられ、最後の "#" は ".vim" で置き換えられます。したがっ
て、"netlib/ftp.vim" となります。Unixの場合、これに使われるライブラリスクリプ
トは次のようになります:
~/.vim/autoload/netlib/ftp.vim
ここで、関数はこのように定義されています:
関数が定義されている名前は、関数を呼び出すときに使われる名前と全く同じであるこ
とに注意してください。また、最後の '#' の前の部分は、サブディレクトリとスクリ
プト名に完全に一致しています。
変数にも同じメカニズムが使用できます:
これによりスクリプト "autoload/dutch.vim" がロードされ、次のような内容が含ま
れる必要があります:
参考文献: autoload。
==============================================================================
52.4 他に使えるメカニズム
複数のファイルを使用するのが面倒で、すべてを1つのスクリプトにまとめておくのを
好む人もいます。その結果として、起動が遅くなるのを回避するため、小さな部分のみ
を定義し、残りは実際に使用されるまで延期するメカニズムがあります。
write-plugin-quickload
基本的な考え方は、プラグインは2回ロードされるということです。初回は、機能を提
供するためのユーザーコマンドとマッピングが定義されます。2回目は、その機能を実
装する関数が定義されます。
高速ロードがスクリプトを2回ロードすることを意味するのは意外に思われるかもしれ
ません。つまり、初回は素早く読み込み、2回目にスクリプトの大部分を読み込ませる
ということです。この機能は、実際に使用するときにのみ発生します。常に機能を使用
する場合、実際には遅くなります!
これは、FuncUndefined 自動コマンドを使用しています。上で説明した autoload 機
能とは異なる動作をします。
以下の例は、その方法を示しています:
スクリプトの初回ロード時は "s:did_load" は未設定です。"if" と "endif" の間のコ
マンドが実行されます。これは :finish コマンドで終わり、残りのスクリプトは実
行されません。
スクリプトの2回目ロード時は "s:did_load" は存在し、"endif" 以降のコマンドが実
行されます。これは(長い可能性のある) BufNetRead() と BufNetWrite() 関数を定義
します。
あなたのプラグインディレクト内にスクリプトを置くと Vim は初期化時に実行します。
このような流れでイベントが発生します:
1. 起動時にスクリプトが読み込まれた時、"BNRead" コマンドが定義され、<F19> キー
がマッピングされる。FuncUndefined 自動コマンドが定義される。":finish" コ
マンドは、スクリプトを早期に終了させる。
2. ユーザーが BNRead コマンドをタイプするか <F19> キーを押す。BufNetRead()
か BufNetWrite() 関数が呼ばれる。
3. Vim は関数を見つけることができず、FuncUndefined 自動コマンドイベントが発
生する。パターン "BufNet*" は呼び出された関数と一致するため、コマンド
"source fname" が実行される。"fname" は、"<sfile>" (expand() を参照) を展
開したものであるため、スクリプトがどこにあるかに関係なく、スクリプトの名前
と等しくなる。
4. スクリプトは再度読み込まれ、"s:did_load" 変数は存在し、関数が定義される。
ロードされた後の関数が FuncUndefined 自動コマンドのパターンにマッチすること
に注意してください。他のプラグインで定義するパターンにマッチする関数がないよう
にしないといけません。
==============================================================================
52.5 旧来のスクリプトから Vim9 script を使う source-vim9-script
いくつかの場合として持っている旧来の Vim script にて Vim9 script のアイテムを
使いたいことがあります。例えばあなたの .vimrc がプラグインの初期化をする場合な
どです。最良の方法は :import を使うことです。例:
これは、Vim9 script ファイル内でエクスポートされた関数 "NiceInit" を見つけ、ス
クリプトローカルな項目 "myNicePlugin.NiceInit" として使用できるようにします。
:import は、"s:" が指定されていない場合でも、常にスクリプトの名前空間を使用
します。"myNicePlugin.vim" がすでに読み込まれていた場合、再度読み込まれること
はありません。
その上アイテムがグローバルの名前空間に置かれるのを防ぎ (名前の衝突が不測の問題
になり得ます)、そしてたとえ何度もアイテムをインポートしても、スクリプトの読み
込みがただ一度であることを意味します。
いくつかの場合、例えばテストなどで、ただ Vim9 script を読み込みたいだけのこと
があります。大丈夫ですが、グローバルのアイテムだけが利用可能となります。Vim9
script ではこうしたグローバルのアイテムで確実にユニークな名前を使うようにしな
くてはなりません。 例:
==============================================================================
52.6 Vim9 サンプル: comment および highlight-yank プラグイン
comment パッケージ
Vim には、Vim9 script で記述されたコメントプラグインが付属しています。
comment-install
$VIMRUNTIME/pack/dist/opt/comment/ にあるパッケージを確認してください。
highlight-yank プラグイン
ヤンクされた領域をハイライトする例を以下に示します。これは、Vim 9.1.0446 以降
で使用可能な getregionpos() 関数を使用します。
以下の例を新しいファイルにコピーしてプラグインディレクトリに配置すると、次回
Vim を起動したときにアクティブになります。add-plugin:
==============================================================================
次章: usr_90.txt Vim のインストール
Copyright: see manual-copyright vim:tw=78:ts=8:noet:ft=help:norl:
VIM USER MANUAL - by Bram Moolenaar
大きなプラグインを作る
プラグインが単純なこと以上のことを行うと、大きくなる傾向があります。このファイ
ルは、それらが高速に読み込まれるようにする方法と、それらを小さなパーツに分割す
る方法を説明しています。
52.1 エクスポートとインポート
52.2 オートロード
52.3 インポート/エクスポートなしのオートロード
52.4 他に使えるメカニズム
52.5 旧来のスクリプトから Vim9 script を使う
52.6 Vim9 サンプル: comment および highlight-yank プラグイン
次章: usr_90.txt Vim のインストール
前章: usr_51.txt プラグインを作る
目次: usr_toc.txt
==============================================================================
52.1 エクスポートとインポート
Vim9 script は大きな Vim script を容易に書けるようにデザインされています。他の
スクリプト言語、特に TypeScript のようになっています。また、処理内の関数はコン
パイルされ素早く実行できます。これにより Vim9 script はとても速く、最大100倍に
なります。
基本的な考え方は、スクリプトファイルには、スクリプトファイル内でのみ使用される
プライベートな項目と、それらをインポートするスクリプトで使用できるエクスポート
される項目があるということです。これにより、何がどこで定義されているかが非常に
明確になります。
1つの関数をエクスポートし、1つのプライベート関数を持つスクリプトの例から始めま
しょう:
vim9script
export def GetMessage(count: string): string
var nr = str2nr(count)
var result = $'To {nr} we say '
result ..= GetReply(nr)
return result
enddef
var nr = str2nr(count)
var result = $'To {nr} we say '
result ..= GetReply(nr)
return result
enddef
def GetReply(nr: number): string
if nr == 42
return 'yes'
elseif nr == 22
return 'maybe'
else
return 'no'
endif
enddef
if nr == 42
return 'yes'
elseif nr == 22
return 'maybe'
else
return 'no'
endif
enddef
export は Vim9 script でのみ動くので vim9script コマンドが必要です。
export def GetMessage(... の行は export から始まっていて、この関数が他のス
クリプトから呼び出すことができることを意味します。def GetReply(... の行は
export で始まっておらず、これはスクリプトローカル関数であり、このスクリプト
ファイル内でのみ使用できます。
次にインポートされるスクリプトについて説明します。この例の中ではこの配置を使用
しており、これは "pack" ディレクトリ下のプラグインに適しています:
.../plugin/theplugin.vim
.../lib/getmessage.vim
"..." ディレクトリが 'runtimepath' に追加されていると仮定すると、Vim は
"plugin" ディレクトリからプラグインを探し "theplugin.vim" を読み込みます。Vim
は "lib" ディレクトリを認識しません、そこに任意のスクリプトを置くことができま
す。
上の GetMessage() をエクスポートしているスクリプトは lib/getmessage.vim 内に
あります。GetMessage() 関数は plugin/theplugin.vim 内にて使用されます:
vim9script
import "../lib/getmessage.vim"
command -nargs=1 ShowMessage echomsg getmessage.GetMessage(<f-args>)
command -nargs=1 ShowMessage echomsg getmessage.GetMessage(<f-args>)
import コマンドは "../" で始まる相対パスを使用しています。これは、1つ上のディ
レクトリに移動することを意味します。他の種類のパスについては、:import コマン
ドを参照してください。
プラグインが提供するコマンドを試す方法:
ShowMessage 1
To 1 we say no ShowMessage 22
To 22 we say maybe関数 GetMessage() には、インポートしたスクリプト名 "getmessage" がプリフィック
スとして付けられていることに注意してください。こうすることで、使用されるすべて
のインポートされた関数について、それがどのスクリプトからインポートされたかが分
かります。複数のスクリプトをインポートする場合、それぞれで GetMessage() 関数を
定義できます:
vim9script
import "../lib/getmessage.vim"
import "../lib/getother.vim"
command -nargs=1 ShowMessage echomsg getmessage.GetMessage(<f-args>)
command -nargs=1 ShowOther echomsg getother.GetMessage(<f-args>)
import "../lib/getother.vim"
command -nargs=1 ShowMessage echomsg getmessage.GetMessage(<f-args>)
command -nargs=1 ShowOther echomsg getother.GetMessage(<f-args>)
インポートしたスクリプトの名前が長いあるいは色々な箇所で使う場合、引数に "as"
を追加することで短くできます:
import "../lib/getmessage.vim" as msg
command -nargs=1 ShowMessage echomsg msg.GetMessage(<f-args>)
command -nargs=1 ShowMessage echomsg msg.GetMessage(<f-args>)
再読み込み
1つ覚えておくべきこと: インポートされた "lib/getmessage.vim" スクリプトは1度だ
け読み込まれます。インポート済みで2度目に読み込む時はスキップされ、項目は最初
に作成された以降そのままです。これはインポートコマンドが他のスクリプト内にあ
るか、再読み込みされた同じスクリプト内にあるかは関係ありません。
これはプラグインを使用する場合は効率的ですが、プラグインを開発中の場合は、イン
ポート後に "lib/getmessage.vim" を変更しても効果がありません。Vim を終了し、再
起動する必要があります。(理論的根拠: スクリプトで定義された項目は、コンパイル
された関数で使用できます。スクリプトを再度読み込むと、これらの関数が壊れる可能
性があります)。
グローバルの使用
時には、グローバル変数や関数を使用して、どこでも使えるようにしたい場合がありま
す。プラグインに設定を渡すグローバル変数がその良い例です。他のスクリプトが同じ
名前を使うのを避けるために、他の場所で使われる可能性が非常に低いプリフィックス
を使用します。例えば、"mytags" プラグインがある場合、次のように使用します:
g:mytags_location = '$HOME/project'
g:mytags_style = 'fast'
g:mytags_style = 'fast'
==============================================================================
52.2 オートロード
大きなスクリプトを分割しても、スクリプトが使用された瞬間にすべての行がロードさ
れ、実行されます。import するたびに、インポートしたスクリプトをロードして、
そこで定義されている項目を探します。これはエラーを早期に発見するためには良いこ
とですが、同時に時間もかかります。そのため、その機能があまり使用されない場合
は、無駄な時間がかかってしまいます。
import でスクリプトをすぐにロードするのではなく、必要になるまで延期すること
ができます。上記の例を使用すると、plugin/theplugin.vim スクリプトで行う必要が
ある変更は1箇所だけです:
import autoload "../lib/getmessage.vim"
スクリプトの残りの部分は何も変更する必要はありません。ただし、型はチェックされ
ません。GetMessage() 関数が使用されるまで、その存在すらチェックされません。ス
クリプトにとってどちらがより重要かを決定する必要があります: 高速な起動か早期に
エラーが分かるか。すべての動作を確認した後で、"autoload" 引数を追加することも
できます。
オートロードディレクトリ
もう1つの形式は絶対パスでも相対パスでもないスクリプト名で autoload を使用する
ことです:
import autoload "monthlib.vim"
これはスクリプト "monthlib.vim" を 'runtimepath' のオートロードディレクトリの
中から検索します。Unix では、ディレクトリの1つが "~/.vim/autoload" であること
が多いです。これはまた 'packpath' の、その下の "start" からも検索します。
この方法の主要な利点として、このスクリプトを他のスクリプトと共有するのが容易で
あることです。Vim が 'runtimepath' 内の "autoload" ディレクトリから検索するた
め、スクリプト名は一意である必要があり、プラグインはいくつかのプラグインマネー
ジャーとともに利用される場合では、'runtimepath' にディレクトリを追加されること
があり、それぞれが "autoload" ディレクトリを持っているためです。
オートロードなしは:
import "monthlib.vim"
Vim は 'runtimepath' のインポートディレクトリ内からスクリプト "monthlib.vim"
を検索します。Note この場合、"autoload" を追加または削除すると、スクリプトが見
つかる場所が変わります。相対パスまたは絶対パスでは、場所は変わりません。
==============================================================================
52.3 インポート/エクスポートなしのオートロード
write-library-script
インポート/エクスポート以前のメカニズムは依然として使用でき一部ユーザーは多少
単純であると感じるかもしれません。それは特別な名前によって関数を呼び出すという
アイデアです。その関数はオートロードスクリプト内にあります。そのスクリプトのこ
とをライブラリスクリプトと呼びます。
オートロードのメカニズムは、関数名が "#" 文字を含んでいることが前提となってい
ます:
mylib#myfunction(arg)
Vim は埋め込まれた "#" 文字によって関数名を認識し、まだ定義されていない場合は
"autoload/mylib.vim" というスクリプトを 'runtimepath' から探します。そのスクリ
プトは "mylib#myfunction()" 関数を定義している必要があります。言うまでもなく、
"mylib" という名前は "#" の前の部分であり、".vim" を追加してスクリプト名として
使用されます。
mylib.vim スクリプト内に他の多くの関数を置ことができ、ライブラリスクリプト内の
構成は自由です。ただし、'#' の前部分がスクリプト名に一致する関数名を使用する必
要があります。そうしないと、Vim はロードするスクリプトを認識できません。この点
がインポート/エクスポートのメカニズムとの違いになります。
本当に夢中になり多数のライブラリスクリプトを書くのであれば、サブディレクトリを
使用したいでしょう。例:
netlib#ftp#read('somefile')
ここでは、スクリプト名は、関数名から最後の "#" までが取得されます。途中の "#"
はスラッシュで置き換えられ、最後の "#" は ".vim" で置き換えられます。したがっ
て、"netlib/ftp.vim" となります。Unixの場合、これに使われるライブラリスクリプ
トは次のようになります:
~/.vim/autoload/netlib/ftp.vim
ここで、関数はこのように定義されています:
def netlib#ftp#read(fname: string)
# Read the file fname through ftp
enddef
# Read the file fname through ftp
enddef
関数が定義されている名前は、関数を呼び出すときに使われる名前と全く同じであるこ
とに注意してください。また、最後の '#' の前の部分は、サブディレクトリとスクリ
プト名に完全に一致しています。
変数にも同じメカニズムが使用できます:
var weekdays = dutch#weekdays
これによりスクリプト "autoload/dutch.vim" がロードされ、次のような内容が含ま
れる必要があります:
var dutch#weekdays = ['zondag', 'maandag', 'dinsdag', 'woensdag',
\ 'donderdag', 'vrijdag', 'zaterdag']
\ 'donderdag', 'vrijdag', 'zaterdag']
参考文献: autoload。
==============================================================================
52.4 他に使えるメカニズム
複数のファイルを使用するのが面倒で、すべてを1つのスクリプトにまとめておくのを
好む人もいます。その結果として、起動が遅くなるのを回避するため、小さな部分のみ
を定義し、残りは実際に使用されるまで延期するメカニズムがあります。
write-plugin-quickload
基本的な考え方は、プラグインは2回ロードされるということです。初回は、機能を提
供するためのユーザーコマンドとマッピングが定義されます。2回目は、その機能を実
装する関数が定義されます。
高速ロードがスクリプトを2回ロードすることを意味するのは意外に思われるかもしれ
ません。つまり、初回は素早く読み込み、2回目にスクリプトの大部分を読み込ませる
ということです。この機能は、実際に使用するときにのみ発生します。常に機能を使用
する場合、実際には遅くなります!
これは、FuncUndefined 自動コマンドを使用しています。上で説明した autoload 機
能とは異なる動作をします。
以下の例は、その方法を示しています:
" Vim global plugin for demonstrating quick loading
" Last Change: 2005 Feb 25
" Maintainer: Bram Moolenaar <Bram@vim.org>
" License: This file is placed in the public domain.
" Last Change: 2005 Feb 25
" Maintainer: Bram Moolenaar <Bram@vim.org>
" License: This file is placed in the public domain.
if !exists("s:did_load")
command -nargs=* BNRead call BufNetRead(<f-args>)
map <F19> :call BufNetWrite('something')<CR>
command -nargs=* BNRead call BufNetRead(<f-args>)
map <F19> :call BufNetWrite('something')<CR>
let s:did_load = 1
exe 'au FuncUndefined BufNet* source ' .. expand('<sfile>')
finish
endif
exe 'au FuncUndefined BufNet* source ' .. expand('<sfile>')
finish
endif
function BufNetRead(...)
echo 'BufNetRead(' .. string(a:000) .. ')'
" read functionality here
endfunction
echo 'BufNetRead(' .. string(a:000) .. ')'
" read functionality here
endfunction
function BufNetWrite(...)
echo 'BufNetWrite(' .. string(a:000) .. ')'
" write functionality here
endfunction
echo 'BufNetWrite(' .. string(a:000) .. ')'
" write functionality here
endfunction
スクリプトの初回ロード時は "s:did_load" は未設定です。"if" と "endif" の間のコ
マンドが実行されます。これは :finish コマンドで終わり、残りのスクリプトは実
行されません。
スクリプトの2回目ロード時は "s:did_load" は存在し、"endif" 以降のコマンドが実
行されます。これは(長い可能性のある) BufNetRead() と BufNetWrite() 関数を定義
します。
あなたのプラグインディレクト内にスクリプトを置くと Vim は初期化時に実行します。
このような流れでイベントが発生します:
1. 起動時にスクリプトが読み込まれた時、"BNRead" コマンドが定義され、<F19> キー
がマッピングされる。FuncUndefined 自動コマンドが定義される。":finish" コ
マンドは、スクリプトを早期に終了させる。
2. ユーザーが BNRead コマンドをタイプするか <F19> キーを押す。BufNetRead()
か BufNetWrite() 関数が呼ばれる。
3. Vim は関数を見つけることができず、FuncUndefined 自動コマンドイベントが発
生する。パターン "BufNet*" は呼び出された関数と一致するため、コマンド
"source fname" が実行される。"fname" は、"<sfile>" (expand() を参照) を展
開したものであるため、スクリプトがどこにあるかに関係なく、スクリプトの名前
と等しくなる。
4. スクリプトは再度読み込まれ、"s:did_load" 変数は存在し、関数が定義される。
ロードされた後の関数が FuncUndefined 自動コマンドのパターンにマッチすること
に注意してください。他のプラグインで定義するパターンにマッチする関数がないよう
にしないといけません。
==============================================================================
52.5 旧来のスクリプトから Vim9 script を使う source-vim9-script
いくつかの場合として持っている旧来の Vim script にて Vim9 script のアイテムを
使いたいことがあります。例えばあなたの .vimrc がプラグインの初期化をする場合な
どです。最良の方法は :import を使うことです。例:
import 'myNicePlugin.vim'
call myNicePlugin.NiceInit('today')
call myNicePlugin.NiceInit('today')
これは、Vim9 script ファイル内でエクスポートされた関数 "NiceInit" を見つけ、ス
クリプトローカルな項目 "myNicePlugin.NiceInit" として使用できるようにします。
:import は、"s:" が指定されていない場合でも、常にスクリプトの名前空間を使用
します。"myNicePlugin.vim" がすでに読み込まれていた場合、再度読み込まれること
はありません。
その上アイテムがグローバルの名前空間に置かれるのを防ぎ (名前の衝突が不測の問題
になり得ます)、そしてたとえ何度もアイテムをインポートしても、スクリプトの読み
込みがただ一度であることを意味します。
いくつかの場合、例えばテストなどで、ただ Vim9 script を読み込みたいだけのこと
があります。大丈夫ですが、グローバルのアイテムだけが利用可能となります。Vim9
script ではこうしたグローバルのアイテムで確実にユニークな名前を使うようにしな
くてはなりません。 例:
source ~/.vim/extra/myNicePlugin.vim
call g:NicePluginTest()
call g:NicePluginTest()
==============================================================================
52.6 Vim9 サンプル: comment および highlight-yank プラグイン
comment パッケージ
Vim には、Vim9 script で記述されたコメントプラグインが付属しています。
comment-install
$VIMRUNTIME/pack/dist/opt/comment/ にあるパッケージを確認してください。
highlight-yank プラグイン
ヤンクされた領域をハイライトする例を以下に示します。これは、Vim 9.1.0446 以降
で使用可能な getregionpos() 関数を使用します。
以下の例を新しいファイルにコピーしてプラグインディレクトリに配置すると、次回
Vim を起動したときにアクティブになります。add-plugin:
vim9script
def HighlightedYank(hlgroup = 'IncSearch', duration = 300, in_visual = true)
if v:event.operator ==? 'y'
if !in_visual && visualmode() != null_string
visualmode(1)
return
endif
var [beg, end] = [getpos("'["), getpos("']")]
var type = v:event.regtype ?? 'v'
var pos = getregionpos(beg, end, {type: type})
var end_offset = (type == 'V' || v:event.inclusive) ? 1 : 0
var m = matchaddpos(hlgroup, pos->mapnew((_, v) => {
var col_beg = v[0][2] + v[0][3]
var col_end = v[1][2] + v[1][3] + end_offset
return [v[0][1], col_beg, col_end - col_beg]
}))
var winid = win_getid()
timer_start(duration, (_) => m->matchdelete(winid))
endif
enddef
if v:event.operator ==? 'y'
if !in_visual && visualmode() != null_string
visualmode(1)
return
endif
var [beg, end] = [getpos("'["), getpos("']")]
var type = v:event.regtype ?? 'v'
var pos = getregionpos(beg, end, {type: type})
var end_offset = (type == 'V' || v:event.inclusive) ? 1 : 0
var m = matchaddpos(hlgroup, pos->mapnew((_, v) => {
var col_beg = v[0][2] + v[0][3]
var col_end = v[1][2] + v[1][3] + end_offset
return [v[0][1], col_beg, col_end - col_beg]
}))
var winid = win_getid()
timer_start(duration, (_) => m->matchdelete(winid))
endif
enddef
autocmd TextYankPost * HighlightedYank()
==============================================================================
次章: usr_90.txt Vim のインストール
Copyright: see manual-copyright vim:tw=78:ts=8:noet:ft=help:norl: