usr_52.txt For Vim バージョン 9.2. Last change: 2026 Jul 27
VIM ユーザーマニュアル 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| で
ロードされるたびに、そこで定義された項目を見つけるために、対象のスクリプトが読
み込まれる。そのため、インポートされるスクリプトが大きいと起動時間が著しく遅く
なる可能性があるが、一方で、エラーがあればインポート時に検出されるという利点も
ある。
起動時の待ち時間を短縮するため、インポートされたスクリプトのロードを、実際に必
要になるまで遅延させることができる。これには autoload キーワードを使用する。
先ほどの例で言えば、plugin/theplugin.vim に必要な変更は 1 箇所だけである:
スクリプトの残りの部分を変更する必要はない。ただし、型チェックは行われず、イン
ポート時には "../lib/getmessage.vim" もロードされない。Vim はファイルが存在し、
読み取り可能かどうかを確認するだけである。GetMessage() 関数が実際に使用される
までは、その関数の存在さえも確認されない。その結果、"getmessage.vim" スクリプ
ト内のエラーは、実行時にのみ検出されることになる。
スクリプトにとって何がより重要かを判断する必要がある: 起動の速さか、それともエ
ラーの早期検出か。
現実的な戦略としては、開発やデバッグ中は autoload キーワードを省略してエラー
が即座に報告されるようにし、プラグインを配布する段階でそれを追加して起動パ
フォーマンスを向上させる、という方法がある。
オートロードディレクトリ
スクリプトを遅延読み込みする別の方法として、以下の例のように、相対パスや絶対パ
スを指定せずに import autoload することである:
Vim は、'runtimepath' に含まれるディレクトリ内の "autoload" ディレクトリからス
クリプトを探す。つまり、スクリプトは "autoload" フォルダ内に配置されている必要
がある。Unix 系システムでは、そのようなディレクトリとして ~/.vim/autoload が
よく使われる。また、'packpath' 内の "start" ディレクトリ配下も検索対象となる。
このようにしてスクリプトがインポートされると、そのスクリプトの公開シンボルは、
インポート元のスクリプト内にとどまるのではなく、グローバルなオートロードの名前
空間を通じて参照されるようになる。
Vim は 'runtimepath' に含まれるすべての "autoload" ディレクトリを検索するため、
スクリプト名には重複しない一意な名前を選ぶこと。プラグインマネージャーは
'runtimepath' に複数のディレクトリを追加することが多く、それらの各ディレクトリ
に "autoload" ディレクトリが含まれている可能性があるからである。
import autoload の 2 つの形式は、以下のようにまとめられる:
- import autoload "foo.vim"
Vim はスクリプトを探す際、'runtimepath' を検索する。こうしたスクリプトは
"autoload" ディレクトリの下に配置する必要があるため、エクスポートされたシン
ボルはグローバルなオートロードの名前空間を通じて使用可能になる。
- import autoload "/some/path/foo.vim"
解決されたパスが "autoload" ディレクトリ配下にある場合、エクスポートされたシ
ンボルも同様にグローバルなオートロードの名前空間に配置される。そうでない場
合、それらのシンボルはインポート元のスクリプト内でのみ有効なローカルなものと
なる。
グローバルなオートロードの名前空間を介してシンボルにアクセスする主な利点は、そ
のスクリプトを他のスクリプトから容易にインポートでき、シンボルを即座に使用でき
ることである。ただし、スクリプトを再読み込みする際にはいくつかの欠点がある。詳
細については vim9-reload を参照。
シンボルがスクリプトローカルなスコープにある場合、それらをスクリプト間で共有す
るには多少の手間がかかり、一律のルールも存在しない。適切なアプローチは、プラグ
インの構成によって異なる。
最後に、以下の例のように autoload やパスを指定せずにスクリプトをインポートす
る場合:
Vim は、'runtimepath' のインポートディレクトリからスクリプト "monthlib.vim" を
検索する。
この場合、autoload キーワードを追加または削除すると、Vim がスクリプトを検索
する場所が変わる。相対パスや絶対パスを使用する場合は、場所は変わらない。
==============================================================================
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 には、Vim9 script で記述された highlight-yank プラグインが付属しています。
hlyank-install。以下は簡略化された実装です: >vim9
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, exclusive: false})
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] + 1
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()
<
完全な例については、$VIMRUNTIME/pack/dist/opt/hlyank/ にあるパッケージを参照
してください。
==============================================================================
次章: usr_90.txt Vim のインストール
Copyright: see manual-copyright vim:tw=78:ts=8:noet:ft=help:norl:
VIM ユーザーマニュアル 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| で
ロードされるたびに、そこで定義された項目を見つけるために、対象のスクリプトが読
み込まれる。そのため、インポートされるスクリプトが大きいと起動時間が著しく遅く
なる可能性があるが、一方で、エラーがあればインポート時に検出されるという利点も
ある。
起動時の待ち時間を短縮するため、インポートされたスクリプトのロードを、実際に必
要になるまで遅延させることができる。これには autoload キーワードを使用する。
先ほどの例で言えば、plugin/theplugin.vim に必要な変更は 1 箇所だけである:
import autoload "../lib/getmessage.vim"
スクリプトの残りの部分を変更する必要はない。ただし、型チェックは行われず、イン
ポート時には "../lib/getmessage.vim" もロードされない。Vim はファイルが存在し、
読み取り可能かどうかを確認するだけである。GetMessage() 関数が実際に使用される
までは、その関数の存在さえも確認されない。その結果、"getmessage.vim" スクリプ
ト内のエラーは、実行時にのみ検出されることになる。
スクリプトにとって何がより重要かを判断する必要がある: 起動の速さか、それともエ
ラーの早期検出か。
現実的な戦略としては、開発やデバッグ中は autoload キーワードを省略してエラー
が即座に報告されるようにし、プラグインを配布する段階でそれを追加して起動パ
フォーマンスを向上させる、という方法がある。
オートロードディレクトリ
スクリプトを遅延読み込みする別の方法として、以下の例のように、相対パスや絶対パ
スを指定せずに import autoload することである:
import autoload "monthlib.vim"
Vim は、'runtimepath' に含まれるディレクトリ内の "autoload" ディレクトリからス
クリプトを探す。つまり、スクリプトは "autoload" フォルダ内に配置されている必要
がある。Unix 系システムでは、そのようなディレクトリとして ~/.vim/autoload が
よく使われる。また、'packpath' 内の "start" ディレクトリ配下も検索対象となる。
このようにしてスクリプトがインポートされると、そのスクリプトの公開シンボルは、
インポート元のスクリプト内にとどまるのではなく、グローバルなオートロードの名前
空間を通じて参照されるようになる。
Vim は 'runtimepath' に含まれるすべての "autoload" ディレクトリを検索するため、
スクリプト名には重複しない一意な名前を選ぶこと。プラグインマネージャーは
'runtimepath' に複数のディレクトリを追加することが多く、それらの各ディレクトリ
に "autoload" ディレクトリが含まれている可能性があるからである。
import autoload の 2 つの形式は、以下のようにまとめられる:
- import autoload "foo.vim"
Vim はスクリプトを探す際、'runtimepath' を検索する。こうしたスクリプトは
"autoload" ディレクトリの下に配置する必要があるため、エクスポートされたシン
ボルはグローバルなオートロードの名前空間を通じて使用可能になる。
- import autoload "/some/path/foo.vim"
解決されたパスが "autoload" ディレクトリ配下にある場合、エクスポートされたシ
ンボルも同様にグローバルなオートロードの名前空間に配置される。そうでない場
合、それらのシンボルはインポート元のスクリプト内でのみ有効なローカルなものと
なる。
グローバルなオートロードの名前空間を介してシンボルにアクセスする主な利点は、そ
のスクリプトを他のスクリプトから容易にインポートでき、シンボルを即座に使用でき
ることである。ただし、スクリプトを再読み込みする際にはいくつかの欠点がある。詳
細については vim9-reload を参照。
シンボルがスクリプトローカルなスコープにある場合、それらをスクリプト間で共有す
るには多少の手間がかかり、一律のルールも存在しない。適切なアプローチは、プラグ
インの構成によって異なる。
最後に、以下の例のように autoload やパスを指定せずにスクリプトをインポートす
る場合:
import "monthlib.vim"
Vim は、'runtimepath' のインポートディレクトリからスクリプト "monthlib.vim" を
検索する。
この場合、autoload キーワードを追加または削除すると、Vim がスクリプトを検索
する場所が変わる。相対パスや絶対パスを使用する場合は、場所は変わらない。
==============================================================================
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 には、Vim9 script で記述された highlight-yank プラグインが付属しています。
hlyank-install。以下は簡略化された実装です: >vim9
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, exclusive: false})
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] + 1
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()
<
完全な例については、$VIMRUNTIME/pack/dist/opt/hlyank/ にあるパッケージを参照
してください。
==============================================================================
次章: usr_90.txt Vim のインストール
Copyright: see manual-copyright vim:tw=78:ts=8:noet:ft=help:norl: