repeat.txt For Vim バージョン 8.2. Last change: 2021 Nov 24
VIMリファレンスマニュアル by Bram Moolenaar
繰り返しコマンド、Vim script とデバッグ repeating
繰り返しについてはユーザーマニュアルの26章usr_26.txtに紹介がある。
1. 単発繰り返し single-repeat
2. 多重繰り返し multi-repeat
3. 複雑な繰り返し complex-repeat
4. Vim script を使う using-scripts
5. Vimパッケージを使う packages
6. Vimパッケージを作る package-create
7. スクリプトのデバッグ debug-scripts
8. プロファイリング profiling
==============================================================================
1. 単発繰り返し single-repeat
.
. 最後の変更を繰り返す。変更の回数は[count]で指定した回
数で置き換えられる。'cpoptions' に 'y' フラグが含まれ
てる時には、ヤンクコマンドも繰り返す。コマンドラインコ
マンドは繰り返さない。
単純な変更は "." コマンドで繰り返すことができる。回数を指定しなければ、最後の
変更の回数が使用される。回数を指定した場合、最後のそれと置き換えられる。
v:count と v:count1 が設定される。
最後に行なわれた変更が番号付きレジスタの指定を含んでいた場合、レジスタ番号は増
加される。これをどのように使うかの例はredo-registerを参照。
ビジュアル選択を使用したコマンドを繰り返す時は、同じ「サイズ」の範囲が使用され
ることに注意。visual-repeatを参照。
@:
@: 最後のコマンドラインを[count]回繰り返す。
{+cmdline_histが無効にされていると使えない}
==============================================================================
2. 多重繰り返し multi-repeat
:g :global E148
:[range]g[lobal]/{pattern}/[cmd]
[range]の範囲で{pattern}にマッチする行に対して、Exコマ
ンド[cmd](省略した場合 ":p")を実行する。
:[range]g[lobal]!/{pattern}/[cmd]
[range]の範囲で{pattern}にマッチしない行に対して、Exコ
マンド[cmd](省略した場合 ":p")を実行する。
:v :vglobal
:[range]v[global]/{pattern}/[cmd]
:g! と同じ。
例:
できる。これはコマンドの処理速度もより速くする。
{pattern} の両側の '/' の代わりにどんなシングルバイト文字でも使うことができる。
しかしアルファベット、'\'、'"'、'|' は使えない。
これは、検索パターンや置換文字列に '/' が含まれる場合に便利である。
パターンの定義については pattern を参照。
NOTE [cmd] は範囲指定を含むかもしれない。実例は collapse や
edit-paragraph-join を参照。
globalコマンドの動作はまず第1に[range]の行をスキャンしマッチした行すべてに印を
つける(複数行にかかるパターンではマッチの最初の行だけが重要である)。
次のスキャンでマークされたすべての行について、カーソルがその行にあるかのように
[cmd]が実行される。":v" と ":g!" の場合は、マークされていないすべての行につい
てコマンドが実行される。行が削除された場合そのマークは消滅する。
省略した場合の[range]はバッファ全体(1,$)である。コマンドを中断するには "CTRL-C"
を使用する。ある行についてエラーメッセージが与えられると、そのラインに対するコ
マンドは中断されglobalコマンドはマッチした次の行の処理を続ける。
E147
このコマンドが再帰的に使われるとき、それは一行のみに働く。この時は範囲の指定は
許されていない。これはあるパターンにマッチして別のパターンにマッチしない行を見
つけるのに便利だ:
いものがあるときにだけ {cmd} を実行する。
非Exコマンドを実行するには :normal コマンドを使用すれば良い:
Vim は全部のマッチに 1 つ 1 つについて、コマンドの残りを期待して貴方の入力を待
ち続けるだろう。画面は更新されないので、いま何をしているのかわからないだろう。
:normal を参照。
undo/redoコマンドはglobalコマンドを一度にundo/redoする。以前の文脈マークだけが
一度設定される("''" でグローバルコマンド実行前にカーソルがあった場所に戻ること
ができる)。
globalコマンドは最後に使用した検索パターンと、最後に使用した置換パターンの両方
を設定する (これはvi互換)。これにより全体に対して文字列置換を行うのが簡単にな
る:
:g/pat/s//PAT/g
これは全ての "pat" を "PAT" に置き換える。同じことがこれでも可能:
:%s/pat/PAT/g
こっちのほうが2文字短い!
Ex モード中で "global" を使い、そのコマンドに ":visual" を指定する場合はやや特
殊である。これを行うと、マッチする行へ移動してノーマルモードに入るので、Q を
押して Ex モードへ戻るまでコマンドを実行することができる。これがマッチする各行
に対して繰り返される。これを行っている間は ":global" を使うことはできない。中
止するには CTRL-C を2回押すこと。
==============================================================================
3. 複雑な繰り返し complex-repeat
q recording
q{0-9a-zA-Z"} タイプした文字をレジスタ{0-9a-zA-Z"}にレコーディングす
る(大文字なら追記)。レジスタを実行中は 'q' コマンドは
無効化される。マッピングや :normal の中でも機能しな
い。
Note: もしレコーディングに使っているレジスタが、その最
中に y や p で使われた場合、恐らく期待しない結果に
なるだろう。なぜなら、p で貼り付けられる内容は記録さ
れたマクロのものになり、y でコピーを行うと記録された
マクロを上書きしてしまうからである。
Note: あなたのタイプ中にレコーディングしたとき、マッピ
ングがあればそれ由来のキーが記録され、それが再生され
る。それは例えば、アンドゥのようにコマンドがタイプされ
たときだけ同期するような場合に重要である。
q レコーディングを終了する。(実装のメモ: レコーディング
を終了する 'q' は、それがマッピングの結果であってもレ
ジスタに記録されない)
@
@{0-9a-z".=*+} レジスタ {0-9a-z".=*+} の内容を [count] 回実行する。
Note: レジスタ '%' (現在のファイルの名前) と '#' (オル
タネートファイルの名前) は使用できない。
レジスタはマッピングと同様に実行される。つまり、
'wildchar' と 'wildcharm' の違いが動作に影響する。
そして同じ方法でアンドゥをしても、動作が同期しないかも
しれない。
"@=" を使用すると式を入力するためのプロンプトが表示さ
れ、そこに入力した式の評価結果が実行される。
@: も参照。
@@ E748
@@ 直前の @{0-9a-z":*} を [count] 回繰り返す。
:@
:[addr]@{0-9a-z".=*+} レジスタ{0-9a-z".=*+}の内容をExコマンドとして実行する。
まず最初にカーソルを[addr]行に設定する(省略した場合現
在の行)。レジスタの最終行に<CR>が含まれない場合、
'cpoptions' に 'e' フラグが含まれていれば自動的に追加
される。
":@=" には最後に評価された式が使用される。式の評価結果
がExコマンドとして実行される。
これらのコマンド内ではマッピングは行われない。
レジスタに行指向テキストが格納され、行の先頭が行継続
line-continuation 文字 (\) が置かれていた時、前の行
と連結される。これは Vim script の一部をヤンクして実行
するときに便利である。
将来: 指定された範囲の各々の行に対してレジスタの内容が
実行されるだろう。
:[addr]*{0-9a-z".=+} :star-compatible
'cpoptions' cpo-star に '*' が存在する場合は、":@"
と同手段として ":*" を使用する。これは、'nocompatible'
が使用されている場合、デフォルトではない。'*' フラグが
'cpoptions' に存在しない場合、":*" は ":'<,'>" のエイ
リアスであり、ビジュアル領域を選択 :star する。
:@:
:[addr]@: 最後のコマンドラインを繰り返す。まずカーソルを[addr]行
に設定する(省略した場合現在の行)。
:[addr]@ :@@
:[addr]@@ 最後の :@{register} を繰り返す。まず最初にカーソルを
[addr]行に設定する(省略した場合現在の行)。
==============================================================================
4. Vim script を使う using-scripts
Vim script の書き方はユーザーマニュアルの41章usr_41.txtを参照。
:so :source load-vim-script
:so[urce] {file} Exコマンドを{file}から読み込む。これは ":" で始まるコ
マンドを列挙したファイルである。
{訳注: 実際に ":" を書く必要はない}
自動コマンド SourcePre が発生する。
:source!
:so[urce]! {file} Vimコマンドを{file}から読み込む。ノーマルモードでファ
イルの内容をあなたがタイプしたのと同じように実行される。
:global, :argdo, :windo, :bufdoで使ったとき、
ループ中や他のコマンドが続けられたときは、コマンドの実
行中は表示は更新されない。
sandbox 内では使用できない。
:ru :runtime
:ru[ntime][!] [where] {file} ..
'runtimepath' か 'packpath' で示された各ディレクトリの
{file}からExコマンドを読み込む。ファイルがなくてもエラ
ーにはならない。
例:
{file}には空白で区切って複数のファイルを指定できる。指
定された{file}は 'runtimepath' の最初のディレクトリ、
次に二番目のディレクトリ、と検索される。{file}に空白を
含めるにはバックスラッシュを使う(しかしファイル名に空
白を含めるのは望ましくない。トラブルのもとである)。
[!] を付けると見つかった全てのファイルを読み込む。付け
なければ最初に見つかったファイルだけを読み込む。
[where] が省略された場合は 'runtimepath' が使われる。
他の値は以下の通り:
START 'packpath' の "start" ディレクトリ以下
を検索する
OPT 'packpath' の "opt" ディレクトリ以下を
検索する
PACK 'packpath' の "start" と "opt" ディレ
クトリ以下を検索する
ALL まず 'runtimepath' が使われ、次に
'packpath' の "start" と "opt" ディレ
クトリ以下を検索する
{file}がワイルドカードを含んでいるとそれは展開される。
例:
ているものである。次のは似ているが:
'verbose' が1以上ならファイルが見つからないときにメッ
セージが表示される。
'verbose' が2以上なら見つかった全てのファイルについて
メッセージが表示される。
:pa :packadd E919
:pa[ckadd][!] {name} 'packpath' 中の任意のプラグインディレクトリを検索し、
見つかったプラグインのファイルを読み込む。ディレクトリ
は以下にマッチしなければならない:
pack/*/opt/{name}
見つかったディレクトリは、もし含まれていなければ
'runtimepath' に追加される。
もしディレクトリ pack/*/opt/{name}/after が存在すれば、
'runtimepath' の最後に追加される。
"pack/*/start" からのパッケージの読み込みがスキップさ
れた場合、次のディレクトリが最初に検索される。
pack/*/start/{name}
Note {name} はディレクトリの名前である。.vimファイルの
名前ではない。以下のパターンにマッチする全てのファイル
が読み込まれる。
pack/*/opt/{name}/plugin/**/*.vim
これにより、ちょうど 'runtimepath' 内のプラグインのよ
うに、"plugin" 以下のサブディレクトリを使うことができ
る。
ファイルタイプの検知が有効化されていない場合(これは通
常.vimrc中の "syntax enable" か "filetype on" コマンド
により行われる)、"{name}/ftdetect/*.vim" ファイルを参
照する。
任意の ! が付けられた場合、プラグインのファイルや
ftdetectのスクリプトは読み込まれず、マッチしたディレク
トリのみ 'runtimepath' に追加される。これは.vimrcに書
く場合は便利である。追加されたプラグインは初期化時に読
み込まれる。load-pluginsを参照(note 各ディレクトリが
他のディレクトリよりも先に挿入されるため、読み込み順序
が逆になる)。
Note ftdetect スクリプトがロードされるようにするには、
filetype plugin indent on を全ての packadd! よりも
「後に」書く必要がある。
また pack-add も参照。
{+eval 機能付きでコンパイルされたときのみ有効}
:packl :packloadall
:packl[oadall][!] 'packpath' 以下の "start" ディレクトリ中の全パッケージ
を読み込む。
最初に、見つかったディレクトリが全て 'runtimepath' に
追加され、次にそのディレクトリ内で見つかったプラグイン
が読み込まれる。これにより、あるプラグインが別のプラグ
インの何か、例えば "autoload" ディレクトリに依存するこ
とが許可される。これがどのように役立つかは
packload-two-steps を参照。
これは通常起動時に.vimrcが読み込まれた後に自動的に行わ
れる。このコマンドはそれよりも前に行うことができる。
パッケージの読み込みは一度だけ行われる。:packloadall
を再度使用しても効果はない。任意の ! が付けられた場合
はすでに読み込みが行われていてもパッケージを読み込む。
Note vimrc ファイル内に :packloadall が使われてい
る場合、'runtimepath' オプションが更新され、後で
'runtimepath' 内のすべてのプラグインが読み込まれる。こ
れはそれらが再び読み込まれることを意味する。プラグイン
はそれを正しく扱うことが期待される。
(スクリプトを読み込む際の)エラーは読み込んでいるスクリ
プトの読み込みのみを中止させる。その他のプラグインは読
み込まれる。
packagesを参照。
{+eval 機能付きでコンパイルされたときのみ有効}
:scripte[ncoding] [encoding] :scripte :scriptencoding E167
スクリプトで使われている文字コードを宣言する。
それ以降の行は必要なら [encoding]から 'encoding' オプ
ションの文字コードに変換される。例:
[encoding]が空のときは変換はされない。これはそれ以降の
行の文字コードの変換を限定するために使える:
変換がシステムによって提供されない場合、エラーメッセー
ジは表示されず変換もされない。ある行が変換できなかった
場合、エラーにはならず元の行が保持される。
"ucs-2" や "ucs-4" を使わないこと。スクリプトをその文
字コードで書くことはできない (NULバイトが含まれてしま
うため)。
スクリプトの最初にutf-8のBOM (Byte Order Mark: バイト
オーダーマーク) があるとVimはそれを認識する。
":scriptencoding utf-8" と書く必要はない。
.vimrc の中で 'encoding' オプションを設定している場
合は、:scriptencoding はそれよりも後に置かなければな
らない。例:
:scriptv[ersion] {version} :scriptv :scriptversion
E999 E984
同じファイルの後に続く行のVimのバージョンを指定する。
読み込まれるスクリプトのトップレベルにのみ適用され、関
数内部には適用されない。
{version}が現在のVimのバージョンがサポートしているもの
よりも高い場合は E999 が与えられる。スクリプトを古い
Vimバージョンで動作するように書き直すか、またはVimを新
しいバージョンに更新する必要がある。バージョン間の変更
点については vimscript-version を参照。
:vim9s[cript] [noclear] :vim9s :vim9script
Vim9-script のコマンドがスクリプトファイルに含まれる
ことをマークする。vim9-namespace も参照。
ファイルの先頭のコマンドである必要がある。
[noclear] については vim9-reload を参照。
+eval 機能がない場合、これは一部のコマンドの文法を変
更する。
Vim9 の文法と方式で単一コマンドを実行するには
:vim9cmd を参照。
:scr :scriptnames
:scr[iptnames] 読み込まれているスクリプトを読み込まれた順番どおりに
全て表示する。数字はスクリプトのID(識別子)<SID>に使
われている。
{+eval付きでコンパイルしないと使えない}
:scr[iptnames][!] {scriptId} :script
スクリプト{scriptId}を編集する。":scriptnames name" は
動作するが、":script name" を使用することを推奨する。
カレントファイルを放棄 abandon できず、[!] も付けら
れていないときは、コマンドは失敗する。
:fini :finish E168
:fini[sh] スクリプトの読み込みを停止する。スクリプトファイルでの
み使える。これはファイルの残りを読み込ませないための手
軽な方法である。:tryを使った後で:finallyを見つける
前に使われると、まず ":finally" と:endtryの間のコマン
ドが実行される。この手続きは入れ子になっている全ての
":try" に対して適用される。入れ子の一番外側の ":endtry"
に達するとスクリプトを停止する。
全てのコマンドとコマンドシーケンスは、名前付きレジスタに格納することで繰り返し
実行することができる。レジスタにコマンドを格納する方法は2つある:
- 記録コマンド "q" を使用する。実際にコマンドをタイプし、実行しながらそれをレ
ジスタに格納する。今、何が起こっているかを確認できるので簡単である。間違いを
したならば、レジスタの内容をいったんファイルへ書き出("p"ut)して、コマンドシー
ケンスを編集して、それからそれを削除して再びレジスタに格納することができる。
レジスタに追加することで継続してレコーディングすることができる(大文字を使用
する)。
- コマンドシーケンスを削除かヤンクしてレジスタに入れる。
良く使うコマンドは ':map' コマンドでファンクションキーに割当てることができる:
別の方法としてコマンドをファイルに記述しておき、それを ':source!' コマンドで読
込んで実行するという方法もある。長いコマンドシーケンスにとっては便利である。
ファンクションキーに複雑なコマンドを割当てるために ':map' コマンドと組み合わせ
ることができる。
':source' コマンドはファイルから一行ずつExコマンドを読込む。キーボード入力が必
要になった場合にはタイプする必要が生じる。':source!' コマンドはスクリプトファ
イルから一字ずつ読込む。各々のキャラクタはユーザーがタイプしたものとして解釈さ
れる。
例: ":!ls" コマンドを実行したとするとhit-enterプロンプトが表示される。"!ls"
を含むファイルを ':source' したならば、自分で<Enter>をタイプする必要があるだろ
う。しかし ':!ls' を含んだファイルを ':source!' したならば、<CR>が見つかるまで
そのファイルから続く文字が読込まれる。":!ls" がファイルの最終行でない限り、
<CR>を自分でタイプする必要はないだろう。
スクリプトファイルの中で ':source[!]' コマンドを使うことも可能なので、階層関係
のあるスクリプトファイルを作ることもできる。':source' コマンドは同時に開くこと
のできるファイル数(だいたい15)と同じだけネスト(入れ子に)することができる。
':source!' コマンドは15段までネストすることができる。
読込まれるファイルの中ではファイル名が必要なところに、"<sfile>" という文字列
(文字通りであってスペシャルキーではない)を使うことができる。この文字列は読込ま
れたファイルのファイル名に置き換えられる。例えば、".vimrc" ファイルと同じ場所
に "other.vimrc" というファイルがあれば、".vimrc" から次のコマンドでそれを読込
むことができる:
スクリプトファイル内では端末依存のキーコードは端末非依存の2文字のコードで表現
される。これは異なる種類の端末でも同じ方法で依存キーコードを使用できることを意
味する。最初のキーコードの文字は0x80つまり128で、画面では "~@" と表される。2つ
目のキャラクタはkey-notationの表にて見ることができる。これらのコードはどれも
CTRL-Vに続けて3つの10進コードを叩くことで入力できる。これはtermcapコード<t_xx>
に対しては使用できない。これらはマッピングの中だけで使うことができる。
:source_crnl W15
Win32: ":source" で読込まれるファイルは通常、行末に<CR><NL>を持っている。これ
らは常に働く。もしも行末に<NL>を持つファイルを使っているならば (例えばUNIXで作
られたファイル)、'fileformats' が空でなくかつ先頭行が<CR>で終わってなければ正
しく認識される。しかしこれは先頭行が ":map <F1> :help^M" (^Mは<CR>) みたいな内
容だった場合には失敗する。ファイルの先頭行が<CR>で終わっていてその1行限りの時、
先頭行から<CR>が失われてしまうのでエラーメッセージが出るだろう。
Mac Classic: ":source" で読み込まれるファイルは通常、行末に<CR>を持っている。
これらは常に機能する。もしも行末に<NL>を持つファイルを使っているならば(例えば
UNIXで作られたファイル)、'fileformats' が空でなくかつ先頭行が<CR>で終わってな
ければ正しく認識される。先頭行に<CR>を持ち<NL>で改行しているファイルを使用しな
いように気をつけること。
その他のシステムでは、Vimは ":source" で読込まれたファイルの行末は<NL>であるこ
とを期待する。これは常に働く。もしも行末が<CR><NL>であるファイル(例えばMS-
Windowsで作られたファイル)を使っているならば、全ての行が末尾に<CR>を持っている
ことになる。これは幾つかのコマンドにとって問題となるだろう(例、マッピング)。自
動的に行末記号を検出する機構はない。なぜなら<CR>で終了するマッピングの定義を
ファイルの先頭に書くことは一般的で、自動検出用の仕組みを作るのが難しいからであ
る。
line-continuation
":source" で読込まれたExコマンドスクリプトのファイル内の長い行は、行継続記号
"\" (backslash) を次行の先頭に挿入することで分割できる。バックスラッシュの前に
空白を挿入することも可能で、これらは無視される。
例: 次の記述は
次の1行と同じ意味として解釈される:
バックスラッシュの前に先行する空白文字は全部無視される。しかしながらバックス
ラッシュのある行の1つ前の行末には、自由に空白文字を挿入することはできない; 付
加的な空白文字が許されるかどうかは、コマンドが分割される位置に依存する。
スペースが必要な場合には、バックスラッシュの直後に書くのがベストである。行末に
スペースを書くと、視認が難しく、誤って削除されてしまうかもしれない。
":append" と ":insert" コマンドには1つ問題がある:
Note 関数の中でその手のコマンドを実行するには、関数定義の際に 'C' フラグを追加
する必要があり、それが実行される際にではない。
line-continuation-comment
継続行の間にコメントを追加するには、行を '"\ ' で始める。バックスラッシュの後の
スペースに注意すること。例:
解説:
多くのプログラムは行継続を、継続する行の末尾にバックスラッシュを置くこ
とで表現する。その方法をVimで採用してしまうと、Viとの互換性に重大な欠
陥ができてしまう。たとえばこのようなViのマッピングを考えるとわかりやす
い:
継続行の中でコメントを開始すると、後続のすべての行がコメントの一部にな
る。それは長い間このようなものだったので、継続行のシーケンスの途中でコ
メントを追加しようとしたとき、\" は有効な継続行であるため、それを使用
することはできなかった。'"\ ' を使用すると最も近いものになるが、少し奇
妙に見えるかもしれない。バックスラッシュの後にスペースを必要とすること
は、これが通常のコメント行にはとても見えないようにするためである。
==============================================================================
5. Vimパッケージを使う packages
Vim script のパッケージは1つかそれ以上のプラグインを含むディレクトリである。
通常のプラグインと比べた長所は以下の通りである:
- パッケージは圧縮ファイルとしてダウンロードでき、独自のディレクトリに展開され
る。よってそのファイルは他のプラグインと混在することがない。これは更新と削除
を簡素化する。
- パッケージには git, mercurial などのリポジトリも使用可能。これはとても更新を
簡素化する。
- パッケージはお互いに依存する複数のプラグインを含むことができる。
- パッケージは起動時に自動的に読み込まれるプラグインと、必要になった時のみ
:packadd により読み込まれるプラグインを含むことができる。
パッケージの使用と自動読み込み
あなたの Vim 関連のファイルは "~/.vim/" にあるとする。
さらにZIP圧縮ファイル "/tmp/foopack.zip" からパッケージを追加したい場合は以下
の通りである:
% mkdir -p ~/.vim/pack/foo
% cd ~/.vim/pack/foo
% unzip /tmp/foopack.zip
"foo" というディレクトリ名は任意である。あなたのお好きな名前を付けてよい。
今あなたの ~/.vim の下に以下のファイルがあるはずである:
pack/foo/README.txt
pack/foo/start/foobar/plugin/foo.vim
pack/foo/start/foobar/syntax/some.vim
pack/foo/opt/foodebug/plugin/debugger.vim
Vim が起動した時、.vimrcを処理した後、'packpath' に含まれる "pack/*/start" ディ
レクトリの下の全てのディレクトリをスキャンする。最初にそのディレクトリは
'runtimepath' に追加される。次に全てのプラグインがロードされる。
これら2つのステップがどのように役立つかについては、packload-two-steps 参照。
上記の例では "pack/foo/start/foobar/plugin/foo.vim" を見つけて
"~/.vim/pack/foo/start/foobar" を 'runtimepath' に追加する。
もし "foobar" プラグインが作動し 'filetype' を "some" にセットした場合、
'runtimepath' に含まれているため、Vim は上記の syntax/some.vim ファイルを見つ
ける。
もし存在するなら、Vim は ftdetect ファイルもロードする。
Note "pack/foo/opt" 以下のファイルは自動的に読み込まれず、"pack/foo/start" 以
下のファイルのみ読み込まれることに注意すること。"opt" ディレクトリがどのように
使われるかについては下記のpack-addを参照。
パッケージの自動読み込みはプラグインの読み込みを無効化している場合は起こらない。
load-pluginsを参照。
'runtimepath' を更新するためにパッケージを読み込むには:
行われる。
パッケージに "after" ディレクトリがある場合、そのディレクトリは 'runtimepath'
の末尾に追加される。そのため、そこにあるものは全て後でロードされる。
単一プラグインの使用とその自動読み込み
パッケージでなく単一のプラグインがある場合は、余分なディレクトリ階層を作成する
必要がある。
% mkdir -p ~/.vim/pack/foo/start/foobar
% cd ~/.vim/pack/foo/start/foobar
% unzip /tmp/someplugin.zip
これで、次のファイルが作成される。
pack/foo/start/foobar/plugin/foo.vim
pack/foo/start/foobar/syntax/some.vim
ここから上のように動作する。
任意のプラグイン
pack-add
上記の pack ディレクトリから任意のプラグインをロードするには :packadd コマン
ドを使う:
~/.vim/pack/foo/opt/foodebug/plugin/debugger.vim を見つけ読み込む。
これにより何かしらの条件が満たされる時に実行されるようにできる。例えば、Vim が
ある機能をサポートしているかどうかとか、依存したモノが見つからないとか、そうい
うことに依存させることができる。
このコマンドをあなたの .vimrc に入れることで、起動時に任意のプラグインを読み
込むこともできる。
:packadd! foodebug
余分な "!" は Vim が --noplugin で起動されていれば、プラグインがロードされな
いようにするためである。
パッケージが "opt" ディレクトリしか持たなかったとしても一向に構わない。その場
合、それを使いたいときは(明示的に)読み込む必要がある。
どこに何を置くか
:colorscheme で読み込まれるカラースキームは "pack/*/start" と "pack/*/opt"
の下から探し出されるのでどこにでも置くことができる。たとえば、
".vim/pack/mycolors/opt/dark/colors/very_dark.vim" のように、"pack/*/opt" の下
に置くことをお勧めする。
Filetype プラグインはファイルタイプに複数のプラグインがあり、:packadd でロー
ドするプラグインを選択したいのでない限り "pack/*/start" の下に置く必要がある。
例えば、コンパイラのバージョンに依存する場合:
"after" ディレクトリはパッケージで使うには十中八九便利ではない。しかし、使用が
禁じられているわけではない。
==============================================================================
6. Vimパッケージを作る package-create
パッケージとして配布する1つ以上のプラグインを記述していることを前提とする。
2つの無関係なプラグインがある場合、2つのパッケージを使用することで、Vimユーザー
はどれを含めてどれを含めないかを選択できるようになる。あるいは、両プラグインを
オプショナルとして1つのパッケージにし、:packadd で望みのプラグインを追加する
ようユーザーに指示することもできる。
パッケージの配布方法を決める。アーカイブを作成することも、リポジトリを使用する
こともできる。より多くのユーザーがアーカイブを使用できるが、新しいバージョンに
更新するのは少し難しくなる。リポジトリは通常、最新の状態に保つことができるが、
"git" のようなプログラムが必要である。github ではリリースを作成すると自動的に
アーカイブが作られるので、あなたは両方を同時に行うことができる。
ディレクトリ構成は次のようになる。
これにより、ユーザーは次の操作を行うことができる。
ここで "myfoobar" はユーザーが選択できる名前だが、唯一の条件は他のパッケージと
は異なることである。
ドキュメントでは、プラグインの機能について説明し、オプションのプラグインをロー
ドする方法をユーザーに伝える。
このpackaddコマンドをプラグインの1つに追加して、オプションのプラグインが必要な
ときに実行することができる。
:helptags コマンドを実行して、doc/tags ファイルを生成する。この生成されたファ
イルをパッケージに含めるということは、パッケージディレクトリにパッケージを落と
すことができ、ヘルプコマンドがすぐに動作することを意味する。プラグインヘルプを
変更した後にコマンドを再実行することを忘れないでほしい。
プラグイン間の依存関係
packload-two-steps
同じ機能に依存する2つのプラグインがあるとする。共通機能を autoload ディレクト
リに置くことで、自動的に見つかるようにすることができる。あなたのパッケージには
次のファイルがあるとする。
pack/foo/start/one/plugin/one.vim
これは動作する。なぜなら、パッケージをロードすると、プラグインを読み込む前に見
つかったすべてのディレクトリが 'runtimepath' に追加されるからである。
==============================================================================
7. スクリプトのデバッグ debug-scripts
スクリプトの動作を知るためのコードを追加することができるのは当り前として、Vim
はデバッグモードを提供している。これはスクリプトファイルやユーザーファンクショ
ンをステップ実行することやブレークポイントを仕掛けることを可能にする。
NOTE: デバッグモードは未完成である。デバッグはVimの動作に副作用をあたえる。全
てをデバッグするのには使えない。例えば画面がデバッグメッセージで散乱するときな
ど。
デバッグモードの代わりに 'verbose' オプションが使える。大きな値を設定するとVim
の動作についてより詳細なメッセージを得られる。
デバッグモードを開始する debug-mode
デバッグモードを開始するにはこれらの方法のうちどれかを使う:
1. Vimを-D引数付きで起動する:
起こっているのかを調査するのに便利である。副作用としてVimは初期化が完了する
前に安全のためターミナルモードを切替える。
(WindowsやMacintoshの)GUI専用バージョンではGUIウィンドウを開くとすぐにデバッ
グが開始する。これを早めるにはvimrcファイルに ":gui" と書くこと。
:debug
2. ":debug" を前に付けてコマンドを実行する。そのコマンドを実行する間だけデバッ
グできる。特定のスクリプトファイルやユーザー関数をデバッグするのに便利であ
る。自動コマンドから呼び出されるスクリプトや関数にも便利である。例:
3. ブレークポイントをソースファイルやユーザーファンクションに設定する。コマン
ドラインから次のようにできる:
バッグモード中でもブレークポイントを設定できる。
デバッグモード中に実行されるコマンドはそれが実行される前に表示される。コメント
や空の行、実行されない行は飛ばされる。行が "|" を使って二つのコマンドを含んで
いた場合には分けて表示される。
デバッグモード
--------------
デバッグモードに入ると、通常のExコマンドが使える。例えば、変数の値を見るには:
に付けるとグローバル変数の値を表示する:
定することもできる。例えば何が起こっているのかを表示するために 'verbose' を設
定することができる。興味のある部分を実行する前に次のようにするといいだろう:
スクリーンの更新を必要とするコマンドは避けるべきである。なぜならデバッグモード
を抜けるまでその作用に気づき難いからである。例えば:
デバッグモードのためのコマンドラインヒストリが別に用意されている。
NOTE: Vim9 script で、コマンドがスクリプトレベルで記述され次行へ継続するにあ
たって、旧来のバックスラッシュを使わずに行継続されるときは、最初の行のみデバッ
グ出力に表示される。
関数の行番号はその関数の始まりから数える。見ている行の番号を数えるのに苦労する
場合はその関数の書かれたファイルを別のVimで開き、その関数の始まりを探しだし、
"99j" を実行すること。"99" は実際の行番号に合わせて変えること。
さらに、以下のコマンドが使える:
>cont
cont 次のブレークポイントまで実行する。
>quit
quit 異常停止する。これはCTRL-Cを使うことに似ているが、全て
を停止するわけではない。次のブレークポイントで停止す
る。
>next
next コマンドを実行しそれが終わるとデバッグモードに戻る。
ユーザー関数やソースファイルの呼び出し時には呼び出し元
の次の行に進む。
>step
step コマンドを実行しそれが終わるとデバッグモードに戻る。
ユーザー関数やソースファイルの呼び出し時には呼び出し先
の行に進む。
>interrupt
interrupt CTRL-C を使うことに似ているが、次のコマンドを実行する
ためにデバッグモードに戻る場所が ">quit" と違う。例外
割り込みについて:finallyや:catchをテストするのに便
利である。
>finish
finish 実行中のスクリプトやユーザー関数を終了し呼び出し元でデ
バッグモードに戻る。
>bt
>backtrace
>where
backtrace 現在のデバッグセッションの呼び出しスタックトレースを表
bt 示する。
where
>frame
frame N N 番目のスタックフレームへ移動する。+ や - 記号で、相
対的に移動できる。例えば、":frame +3" で 3 つ上のス
タックフレームへ移動する。
>up
up 呼び出しスタックトレースを 1 つ上へ移動する。
>down
down 呼び出しスタックトレースを 1 つ下へ移動する。
デバッグモードのコマンドについて:
- 補完はできない。通常のExコマンドのみ補完できる。
- コマンド名は、他のコマンドが同じ文字で始まらない限り 1 文字まで省略できる。
"f" は "finish" になるので "frame" を省略するには "fr" を用いる。
- <CR>を押すと前回のものを繰り返す。関係ないコマンドを使うとリセットされる
(どうすべきかがわかりにくいため)。
- 同じ名前のExコマンドを使うにはコロンを付けること:
":cont", ":next", ":finish" (省略時も)
vim9-debug
コンパイル済みの :def 関数をデバッグする場合、"step" はすべての命令ではなく、
実行されるすべての行の前で停止する。これにより、ほとんどの場合は非コンパイル関
数のように動作する。ローカル変数へのアクセスは制限されているが可能である:
特定のバイトコード命令ではなく、通常のExコマンドのように実行されるコマンドを実
行する場合、"step" はローカル変数を検査できるコンパイル済みコンテキストで1回、
そしてコマンドを実行する直前に1回停止する。
バックトレースは、関数呼び出しの階層を表示する。例えば:
>bt
3 function One[3]
2 Two[3]
->1 Three[3]
0 Four
行 1: let four = 4
"->" は現在いるフレームを指す。"up"、"down"、"frame N" を使うことで、別のフレー
ムを選択できる。
現在いるフレームの、その関数内でのローカル変数にアクセスできる。現在いるフレー
ムの、現在行の内容を表示する方法はまだない。
ブレークポイントの定義
----------------------
:breaka :breakadd
:breaka[dd] func [lnum] {name}
関数にブレークポイントを設定する。例:
ントを定義できる。
:breaka[dd] file [lnum] {name}
ソースファイルにブレークポイントを設定する。例:
:breaka[dd] here
カレントファイルのカレント行にブレークポイントを設定する。
次を行うのと同様である:
だけ働く。そのファイル中で定義される関数に対しては働かない。
:breaka[dd] expr {expression}
{expression} の評価結果が異なる値となるときに常にブレークする
ブレークポイントを設定する。例:
評価中のエラーは抑制されるので、まだ存在しない変数の名前が使え
る。これはまた、式に間違いがあっても何も気付けないということで
もある。
Note: script-variable を監視する場合、スクリプトが切り替わっ
たときにブレークする。これは、定義されたスクリプト内でのみ、そ
のスクリプト変数が有効だからである。そしてそのスクリプトがいく
つかのその他のスクリプトから呼び出される場合、その特定の変数が
可視となったとき、もしくは再度アクセス不能となったときに常に停
止する。
[lnum] はブレークポイントにする行番号である。Vimはその行かそれ以降で停止する。
省略時すると1行目になる。
:debug-name
{name} はファイル名や関数名のパターンである。パターンは自動コマンドで使われる
ものと同じである。完全に一致しなければならない (パターンが "^" で始まって"$"
で終わるように)。"*" は全ての文字列に一致する。'ignorecase' は使われないが、大
文字と小文字を区別しないために "\c" を使うことができる/\c。関数名には()を付
けないように!
ソースファイル名のパターン検査はファイルのフルネームに対して行われる。例:
関数名のパターン検査は ":function" で表示される名前に対して行われる。しかしな
がら、ローカル関数ではスクリプトのIDを知らずともスクリプトローカル関数との照合
が容易にできるようにスクリプト固有の "<SNR>99_" のような接頭辞は無視される。
Note 関数はまず読み込まれ、後で実行される。読み込まれたときに "file" ブレーク
ポイントがチェックされ、実行されるときに "func" ブレークポイントがチェックされ
る。
ブレークポイントの削除
----------------------
:breakd :breakdel E161
:breakd[el] {nr}
ブレークポイント{nr}を削除する。:breaklistを使って番号を確認
できる。
:breakd[el] *
すべてのブレークポイントを削除する。
:breakd[el] func [lnum] {name}
関数内のブレークポイントを削除する。
:breakd[el] file [lnum] {name}
ソースファイル内のブレークポイントを削除する。
:breakd[el] here
カレントファイルのカレント行のブレークポイントを削除する。
[lnum] が省略されると関数、またはファイルの最初のブレークポイントが削除される。
{name} は ":breakadd" で使った名前と完全に同じでなければならない。"explorer"
と "*explorer.vim"、"*explorer*" は違う。
ブレークポイントを列挙する
--------------------------
:breakl :breaklist
:breakl[ist]
全てのブレークポイントを列挙する。
その他
------
:debugg :debuggreedy
:debugg[reedy]
デバッグモードのコマンドをユーザーから直接得るのではなく標準入
力から読み込む。スクリプトのテストのときに便利である。
例:
:0debugg[reedy]
":debuggreedy" を取り消す。それ以降のデバッグモードコマンドを
使わず、ユーザーから直接デバッグモードコマンドを受け取る。
==============================================================================
8. プロファイリング profile profiling
プロファイリングとは、関数やスクリプトの実行にかかる時間を計測することである。
これを行うには +profile 機能が必要である。
この機能は "huge" 機能つきでコンパイルしたときに含まれる。
また、関数 reltime() を使っても時間を計測できる。この関数には +reltime 機
能だけが必要である。これは "huge" 以外の多くのビルドについてくる。
シンタックスハイライトのプロファイリングについては :syntime を参照せよ。
例えば、one_script.vim スクリプトファイルをプロファイリングするには:
:prof[ile] start {fname} :prof :profile E750
プロファイリングを開始し、終了時に出力を {fname} に出力する。
{fname} 中の "~/" や環境変数は展開される。
{fname} がすでに存在するときは、警告なしに上書きされる。
変数 v:profiling に 1 が代入される。
:prof[ile] pause
次の ":profile continue" が実行されるまでプロファイリングをし
ない。カウントされるべきでない何かを行う時に使うことができる
(例えば外部コマンドなど)。ネストすることはできない。
:prof[ile] continue
":profile pause" の後にこれを実行すると、プロファイリングを再
開する。
:prof[ile] func {pattern}
パターン {pattern} にマッチする関数をプロファイリングする。
{pattern} がどう使われるかは :debug-name を参照。
:prof[ile][!] file {pattern}
パターン {pattern} にマッチするスクリプトファイルをプロファイ
リングする。
{pattern} がどう使われるかは :debug-name を参照。
このコマンドはスクリプトそのものをプロファイリングするだけで、
その中で定義されている関数のプロファイリングは行わない。
[!] がつけられたときは、そのスクリプト中で定義されている全ての
関数のプロファイリングも行う。
Note スクリプトがこのコマンドの後で読み込まれたときだけ、その
プロファイリングは始まる。スクリプト自身にある :profile コマン
ドは働かない。
:profd[el] ... :profd :profdel
指定された引数に対するプロファイリングを停止する。引数について
は :breakdel を参照。
最初は常に ":profile start fname" コマンドで始めなければならない。結果のファイ
ルは Vim が終了するときに書き出される。例えば、特定の1つの関数のプロファイルな
らば:
次に出力の例を挙げる。説明のために行番号が行頭についている:
1 FUNCTION Test2()
2 Called 1 time
3 Total time: 0.155251
4 Self time: 0.002006
5
6 count total (s) self (s)
7 9 0.000096 for i in range(8)
8 8 0.153655 0.000410 call Test3()
9 8 0.000070 endfor
10 " Ask a question
11 1 0.001341 echo input("give me an answer: ")
ヘッダー (1行目から4行目) は関数全体にかかった時間を示している。"Total" はこの
関数を実行している間に経過した時間である。"Self" は "Total" のうち、次のことに
かかった時間を引いたものである:
- 他のユーザー定義関数
- スクリプトの読み込み
- 自動コマンドの実行
- 外部(シェル)プログラム
7行目から11行目は各実行行にかかった時間を示している。実行されない行はカウント
されない。それゆえ、コメント行は決してカウントされない。
Count の桁はその行が何回実行されたかを示す。7行目の "for" コマンドはそれ以下の
行と同様に何回も実行されることに注意すること。これは、ループの終わりを検出する
ためにこの行が何回も実行されるためである。
ユーザー入力待ちにかかった時間は一切カウントされない。それゆえ、input() のプロ
ンプトに反応するのにどれだけ時間がかかろうとも無関係である。
プロファイリングはどこで時間が費やされたかのよい指標を与えてくれるが、多くの
原因によりその結果がごまかされてしまう場合があるということを覚えておくように:
- システム関数 gettimeofday() に依存する時間計測の精度。たとえ時間がマイクロ秒
で表示されていたとしても、1/100秒の精度しかないこともある。
- 実経過時間が計測される。他のプロセスがビジーであると、それが予測できない箇
所で遅れを引き起こす可能性がある。
- 1行に複数のコマンドを書いていると、1つの時間しか得られない。ここのコマンド
に対して時間を見るにはその行を分割すること。
- 各行の時間の総和をとると、たいてい関数全体の時間より小さくなる。各行の間に
オーバーヘッドがある。
- Vim が終了する前に削除された関数はプロファイリング情報を生成しない。必要な
ら変数 v:profiling をチェックすること:
- マルチプロセッサーシステム上では、スリープモードが作動したときや、省力のため
プロセッサーの周波数が下がったとき、プロファイリングが奇妙な結果を出すかもし
れない。
- 関数が再帰的に呼ばれた場合、"self" 時間は正しくない。
vim:tw=78:ts=8:noet:ft=help:norl:
VIMリファレンスマニュアル by Bram Moolenaar
繰り返しコマンド、Vim script とデバッグ repeating
繰り返しについてはユーザーマニュアルの26章usr_26.txtに紹介がある。
1. 単発繰り返し single-repeat
2. 多重繰り返し multi-repeat
3. 複雑な繰り返し complex-repeat
4. Vim script を使う using-scripts
5. Vimパッケージを使う packages
6. Vimパッケージを作る package-create
7. スクリプトのデバッグ debug-scripts
8. プロファイリング profiling
==============================================================================
1. 単発繰り返し single-repeat
.
. 最後の変更を繰り返す。変更の回数は[count]で指定した回
数で置き換えられる。'cpoptions' に 'y' フラグが含まれ
てる時には、ヤンクコマンドも繰り返す。コマンドラインコ
マンドは繰り返さない。
単純な変更は "." コマンドで繰り返すことができる。回数を指定しなければ、最後の
変更の回数が使用される。回数を指定した場合、最後のそれと置き換えられる。
v:count と v:count1 が設定される。
最後に行なわれた変更が番号付きレジスタの指定を含んでいた場合、レジスタ番号は増
加される。これをどのように使うかの例はredo-registerを参照。
ビジュアル選択を使用したコマンドを繰り返す時は、同じ「サイズ」の範囲が使用され
ることに注意。visual-repeatを参照。
@:
@: 最後のコマンドラインを[count]回繰り返す。
{+cmdline_histが無効にされていると使えない}
==============================================================================
2. 多重繰り返し multi-repeat
:g :global E148
:[range]g[lobal]/{pattern}/[cmd]
[range]の範囲で{pattern}にマッチする行に対して、Exコマ
ンド[cmd](省略した場合 ":p")を実行する。
:[range]g[lobal]!/{pattern}/[cmd]
[range]の範囲で{pattern}にマッチしない行に対して、Exコ
マンド[cmd](省略した場合 ":p")を実行する。
:v :vglobal
:[range]v[global]/{pattern}/[cmd]
:g! と同じ。
例:
:g/^Obsolete/d _
:d の後にアンダースコアを使用すると、レジスタやクリップボードの上書きを回避できる。これはコマンドの処理速度もより速くする。
{pattern} の両側の '/' の代わりにどんなシングルバイト文字でも使うことができる。
しかしアルファベット、'\'、'"'、'|' は使えない。
これは、検索パターンや置換文字列に '/' が含まれる場合に便利である。
パターンの定義については pattern を参照。
NOTE [cmd] は範囲指定を含むかもしれない。実例は collapse や
edit-paragraph-join を参照。
globalコマンドの動作はまず第1に[range]の行をスキャンしマッチした行すべてに印を
つける(複数行にかかるパターンではマッチの最初の行だけが重要である)。
次のスキャンでマークされたすべての行について、カーソルがその行にあるかのように
[cmd]が実行される。":v" と ":g!" の場合は、マークされていないすべての行につい
てコマンドが実行される。行が削除された場合そのマークは消滅する。
省略した場合の[range]はバッファ全体(1,$)である。コマンドを中断するには "CTRL-C"
を使用する。ある行についてエラーメッセージが与えられると、そのラインに対するコ
マンドは中断されglobalコマンドはマッチした次の行の処理を続ける。
E147
このコマンドが再帰的に使われるとき、それは一行のみに働く。この時は範囲の指定は
許されていない。これはあるパターンにマッチして別のパターンにマッチしない行を見
つけるのに便利だ:
:g/found/v/notfound/{cmd}
これは、はじめに "found" を含むすべての行を見つけるが、"notfound" にマッチしないものがあるときにだけ {cmd} を実行する。
非Exコマンドを実行するには :normal コマンドを使用すれば良い:
:g/pat/normal {commands}
確実に {commands} が完全なコマンドとして終了するようにすること。そうでないとVim は全部のマッチに 1 つ 1 つについて、コマンドの残りを期待して貴方の入力を待
ち続けるだろう。画面は更新されないので、いま何をしているのかわからないだろう。
:normal を参照。
undo/redoコマンドはglobalコマンドを一度にundo/redoする。以前の文脈マークだけが
一度設定される("''" でグローバルコマンド実行前にカーソルがあった場所に戻ること
ができる)。
globalコマンドは最後に使用した検索パターンと、最後に使用した置換パターンの両方
を設定する (これはvi互換)。これにより全体に対して文字列置換を行うのが簡単にな
る:
:g/pat/s//PAT/g
これは全ての "pat" を "PAT" に置き換える。同じことがこれでも可能:
:%s/pat/PAT/g
こっちのほうが2文字短い!
Ex モード中で "global" を使い、そのコマンドに ":visual" を指定する場合はやや特
殊である。これを行うと、マッチする行へ移動してノーマルモードに入るので、Q を
押して Ex モードへ戻るまでコマンドを実行することができる。これがマッチする各行
に対して繰り返される。これを行っている間は ":global" を使うことはできない。中
止するには CTRL-C を2回押すこと。
==============================================================================
3. 複雑な繰り返し complex-repeat
q recording
q{0-9a-zA-Z"} タイプした文字をレジスタ{0-9a-zA-Z"}にレコーディングす
る(大文字なら追記)。レジスタを実行中は 'q' コマンドは
無効化される。マッピングや :normal の中でも機能しな
い。
Note: もしレコーディングに使っているレジスタが、その最
中に y や p で使われた場合、恐らく期待しない結果に
なるだろう。なぜなら、p で貼り付けられる内容は記録さ
れたマクロのものになり、y でコピーを行うと記録された
マクロを上書きしてしまうからである。
Note: あなたのタイプ中にレコーディングしたとき、マッピ
ングがあればそれ由来のキーが記録され、それが再生され
る。それは例えば、アンドゥのようにコマンドがタイプされ
たときだけ同期するような場合に重要である。
q レコーディングを終了する。(実装のメモ: レコーディング
を終了する 'q' は、それがマッピングの結果であってもレ
ジスタに記録されない)
@
@{0-9a-z".=*+} レジスタ {0-9a-z".=*+} の内容を [count] 回実行する。
Note: レジスタ '%' (現在のファイルの名前) と '#' (オル
タネートファイルの名前) は使用できない。
レジスタはマッピングと同様に実行される。つまり、
'wildchar' と 'wildcharm' の違いが動作に影響する。
そして同じ方法でアンドゥをしても、動作が同期しないかも
しれない。
"@=" を使用すると式を入力するためのプロンプトが表示さ
れ、そこに入力した式の評価結果が実行される。
@: も参照。
@@ E748
@@ 直前の @{0-9a-z":*} を [count] 回繰り返す。
:@
:[addr]@{0-9a-z".=*+} レジスタ{0-9a-z".=*+}の内容をExコマンドとして実行する。
まず最初にカーソルを[addr]行に設定する(省略した場合現
在の行)。レジスタの最終行に<CR>が含まれない場合、
'cpoptions' に 'e' フラグが含まれていれば自動的に追加
される。
":@=" には最後に評価された式が使用される。式の評価結果
がExコマンドとして実行される。
これらのコマンド内ではマッピングは行われない。
レジスタに行指向テキストが格納され、行の先頭が行継続
line-continuation 文字 (\) が置かれていた時、前の行
と連結される。これは Vim script の一部をヤンクして実行
するときに便利である。
将来: 指定された範囲の各々の行に対してレジスタの内容が
実行されるだろう。
:[addr]*{0-9a-z".=+} :star-compatible
'cpoptions' cpo-star に '*' が存在する場合は、":@"
と同手段として ":*" を使用する。これは、'nocompatible'
が使用されている場合、デフォルトではない。'*' フラグが
'cpoptions' に存在しない場合、":*" は ":'<,'>" のエイ
リアスであり、ビジュアル領域を選択 :star する。
:@:
:[addr]@: 最後のコマンドラインを繰り返す。まずカーソルを[addr]行
に設定する(省略した場合現在の行)。
:[addr]@ :@@
:[addr]@@ 最後の :@{register} を繰り返す。まず最初にカーソルを
[addr]行に設定する(省略した場合現在の行)。
==============================================================================
4. Vim script を使う using-scripts
Vim script の書き方はユーザーマニュアルの41章usr_41.txtを参照。
:so :source load-vim-script
:so[urce] {file} Exコマンドを{file}から読み込む。これは ":" で始まるコ
マンドを列挙したファイルである。
{訳注: 実際に ":" を書く必要はない}
自動コマンド SourcePre が発生する。
:source!
:so[urce]! {file} Vimコマンドを{file}から読み込む。ノーマルモードでファ
イルの内容をあなたがタイプしたのと同じように実行される。
:global, :argdo, :windo, :bufdoで使ったとき、
ループ中や他のコマンドが続けられたときは、コマンドの実
行中は表示は更新されない。
sandbox 内では使用できない。
:ru :runtime
:ru[ntime][!] [where] {file} ..
'runtimepath' か 'packpath' で示された各ディレクトリの
{file}からExコマンドを読み込む。ファイルがなくてもエラ
ーにはならない。
例:
:runtime syntax/c.vim
{file}には空白で区切って複数のファイルを指定できる。指
定された{file}は 'runtimepath' の最初のディレクトリ、
次に二番目のディレクトリ、と検索される。{file}に空白を
含めるにはバックスラッシュを使う(しかしファイル名に空
白を含めるのは望ましくない。トラブルのもとである)。
[!] を付けると見つかった全てのファイルを読み込む。付け
なければ最初に見つかったファイルだけを読み込む。
[where] が省略された場合は 'runtimepath' が使われる。
他の値は以下の通り:
START 'packpath' の "start" ディレクトリ以下
を検索する
OPT 'packpath' の "opt" ディレクトリ以下を
検索する
PACK 'packpath' の "start" と "opt" ディレ
クトリ以下を検索する
ALL まず 'runtimepath' が使われ、次に
'packpath' の "start" と "opt" ディレ
クトリ以下を検索する
{file}がワイルドカードを含んでいるとそれは展開される。
例:
:runtime! plugin/**/*.vim
これはVimが起動時にプラグインファイルを読み込むのに使っているものである。次のは似ているが:
:runtime plugin/**/*.vim
これは最初に見つかったファイルだけを読み込む。'verbose' が1以上ならファイルが見つからないときにメッ
セージが表示される。
'verbose' が2以上なら見つかった全てのファイルについて
メッセージが表示される。
:pa :packadd E919
:pa[ckadd][!] {name} 'packpath' 中の任意のプラグインディレクトリを検索し、
見つかったプラグインのファイルを読み込む。ディレクトリ
は以下にマッチしなければならない:
pack/*/opt/{name}
見つかったディレクトリは、もし含まれていなければ
'runtimepath' に追加される。
もしディレクトリ pack/*/opt/{name}/after が存在すれば、
'runtimepath' の最後に追加される。
"pack/*/start" からのパッケージの読み込みがスキップさ
れた場合、次のディレクトリが最初に検索される。
pack/*/start/{name}
Note {name} はディレクトリの名前である。.vimファイルの
名前ではない。以下のパターンにマッチする全てのファイル
が読み込まれる。
pack/*/opt/{name}/plugin/**/*.vim
これにより、ちょうど 'runtimepath' 内のプラグインのよ
うに、"plugin" 以下のサブディレクトリを使うことができ
る。
ファイルタイプの検知が有効化されていない場合(これは通
常.vimrc中の "syntax enable" か "filetype on" コマンド
により行われる)、"{name}/ftdetect/*.vim" ファイルを参
照する。
任意の ! が付けられた場合、プラグインのファイルや
ftdetectのスクリプトは読み込まれず、マッチしたディレク
トリのみ 'runtimepath' に追加される。これは.vimrcに書
く場合は便利である。追加されたプラグインは初期化時に読
み込まれる。load-pluginsを参照(note 各ディレクトリが
他のディレクトリよりも先に挿入されるため、読み込み順序
が逆になる)。
Note ftdetect スクリプトがロードされるようにするには、
filetype plugin indent on を全ての packadd! よりも
「後に」書く必要がある。
また pack-add も参照。
{+eval 機能付きでコンパイルされたときのみ有効}
:packl :packloadall
:packl[oadall][!] 'packpath' 以下の "start" ディレクトリ中の全パッケージ
を読み込む。
最初に、見つかったディレクトリが全て 'runtimepath' に
追加され、次にそのディレクトリ内で見つかったプラグイン
が読み込まれる。これにより、あるプラグインが別のプラグ
インの何か、例えば "autoload" ディレクトリに依存するこ
とが許可される。これがどのように役立つかは
packload-two-steps を参照。
これは通常起動時に.vimrcが読み込まれた後に自動的に行わ
れる。このコマンドはそれよりも前に行うことができる。
パッケージの読み込みは一度だけ行われる。:packloadall
を再度使用しても効果はない。任意の ! が付けられた場合
はすでに読み込みが行われていてもパッケージを読み込む。
Note vimrc ファイル内に :packloadall が使われてい
る場合、'runtimepath' オプションが更新され、後で
'runtimepath' 内のすべてのプラグインが読み込まれる。こ
れはそれらが再び読み込まれることを意味する。プラグイン
はそれを正しく扱うことが期待される。
(スクリプトを読み込む際の)エラーは読み込んでいるスクリ
プトの読み込みのみを中止させる。その他のプラグインは読
み込まれる。
packagesを参照。
{+eval 機能付きでコンパイルされたときのみ有効}
:scripte[ncoding] [encoding] :scripte :scriptencoding E167
スクリプトで使われている文字コードを宣言する。
それ以降の行は必要なら [encoding]から 'encoding' オプ
ションの文字コードに変換される。例:
scriptencoding iso-8859-5
scriptencoding cp932
scriptencoding cp932
[encoding]が空のときは変換はされない。これはそれ以降の
行の文字コードの変換を限定するために使える:
scriptencoding euc-jp
... 変換される ...
scriptencoding
... 変換されない ...
... 変換される ...
scriptencoding
... 変換されない ...
変換がシステムによって提供されない場合、エラーメッセー
ジは表示されず変換もされない。ある行が変換できなかった
場合、エラーにはならず元の行が保持される。
"ucs-2" や "ucs-4" を使わないこと。スクリプトをその文
字コードで書くことはできない (NULバイトが含まれてしま
うため)。
スクリプトの最初にutf-8のBOM (Byte Order Mark: バイト
オーダーマーク) があるとVimはそれを認識する。
":scriptencoding utf-8" と書く必要はない。
.vimrc の中で 'encoding' オプションを設定している場
合は、:scriptencoding はそれよりも後に置かなければな
らない。例:
set encoding=utf-8
scriptencoding utf-8
scriptencoding utf-8
:scriptv[ersion] {version} :scriptv :scriptversion
E999 E984
同じファイルの後に続く行のVimのバージョンを指定する。
読み込まれるスクリプトのトップレベルにのみ適用され、関
数内部には適用されない。
{version}が現在のVimのバージョンがサポートしているもの
よりも高い場合は E999 が与えられる。スクリプトを古い
Vimバージョンで動作するように書き直すか、またはVimを新
しいバージョンに更新する必要がある。バージョン間の変更
点については vimscript-version を参照。
:vim9s[cript] [noclear] :vim9s :vim9script
Vim9-script のコマンドがスクリプトファイルに含まれる
ことをマークする。vim9-namespace も参照。
ファイルの先頭のコマンドである必要がある。
[noclear] については vim9-reload を参照。
+eval 機能がない場合、これは一部のコマンドの文法を変
更する。
Vim9 の文法と方式で単一コマンドを実行するには
:vim9cmd を参照。
:scr :scriptnames
:scr[iptnames] 読み込まれているスクリプトを読み込まれた順番どおりに
全て表示する。数字はスクリプトのID(識別子)<SID>に使
われている。
{+eval付きでコンパイルしないと使えない}
:scr[iptnames][!] {scriptId} :script
スクリプト{scriptId}を編集する。":scriptnames name" は
動作するが、":script name" を使用することを推奨する。
カレントファイルを放棄 abandon できず、[!] も付けら
れていないときは、コマンドは失敗する。
:fini :finish E168
:fini[sh] スクリプトの読み込みを停止する。スクリプトファイルでの
み使える。これはファイルの残りを読み込ませないための手
軽な方法である。:tryを使った後で:finallyを見つける
前に使われると、まず ":finally" と:endtryの間のコマン
ドが実行される。この手続きは入れ子になっている全ての
":try" に対して適用される。入れ子の一番外側の ":endtry"
に達するとスクリプトを停止する。
全てのコマンドとコマンドシーケンスは、名前付きレジスタに格納することで繰り返し
実行することができる。レジスタにコマンドを格納する方法は2つある:
- 記録コマンド "q" を使用する。実際にコマンドをタイプし、実行しながらそれをレ
ジスタに格納する。今、何が起こっているかを確認できるので簡単である。間違いを
したならば、レジスタの内容をいったんファイルへ書き出("p"ut)して、コマンドシー
ケンスを編集して、それからそれを削除して再びレジスタに格納することができる。
レジスタに追加することで継続してレコーディングすることができる(大文字を使用
する)。
- コマンドシーケンスを削除かヤンクしてレジスタに入れる。
良く使うコマンドは ':map' コマンドでファンクションキーに割当てることができる:
別の方法としてコマンドをファイルに記述しておき、それを ':source!' コマンドで読
込んで実行するという方法もある。長いコマンドシーケンスにとっては便利である。
ファンクションキーに複雑なコマンドを割当てるために ':map' コマンドと組み合わせ
ることができる。
':source' コマンドはファイルから一行ずつExコマンドを読込む。キーボード入力が必
要になった場合にはタイプする必要が生じる。':source!' コマンドはスクリプトファ
イルから一字ずつ読込む。各々のキャラクタはユーザーがタイプしたものとして解釈さ
れる。
例: ":!ls" コマンドを実行したとするとhit-enterプロンプトが表示される。"!ls"
を含むファイルを ':source' したならば、自分で<Enter>をタイプする必要があるだろ
う。しかし ':!ls' を含んだファイルを ':source!' したならば、<CR>が見つかるまで
そのファイルから続く文字が読込まれる。":!ls" がファイルの最終行でない限り、
<CR>を自分でタイプする必要はないだろう。
スクリプトファイルの中で ':source[!]' コマンドを使うことも可能なので、階層関係
のあるスクリプトファイルを作ることもできる。':source' コマンドは同時に開くこと
のできるファイル数(だいたい15)と同じだけネスト(入れ子に)することができる。
':source!' コマンドは15段までネストすることができる。
読込まれるファイルの中ではファイル名が必要なところに、"<sfile>" という文字列
(文字通りであってスペシャルキーではない)を使うことができる。この文字列は読込ま
れたファイルのファイル名に置き換えられる。例えば、".vimrc" ファイルと同じ場所
に "other.vimrc" というファイルがあれば、".vimrc" から次のコマンドでそれを読込
むことができる:
:source <sfile>:h/other.vimrc
スクリプトファイル内では端末依存のキーコードは端末非依存の2文字のコードで表現
される。これは異なる種類の端末でも同じ方法で依存キーコードを使用できることを意
味する。最初のキーコードの文字は0x80つまり128で、画面では "~@" と表される。2つ
目のキャラクタはkey-notationの表にて見ることができる。これらのコードはどれも
CTRL-Vに続けて3つの10進コードを叩くことで入力できる。これはtermcapコード<t_xx>
に対しては使用できない。これらはマッピングの中だけで使うことができる。
:source_crnl W15
Win32: ":source" で読込まれるファイルは通常、行末に<CR><NL>を持っている。これ
らは常に働く。もしも行末に<NL>を持つファイルを使っているならば (例えばUNIXで作
られたファイル)、'fileformats' が空でなくかつ先頭行が<CR>で終わってなければ正
しく認識される。しかしこれは先頭行が ":map <F1> :help^M" (^Mは<CR>) みたいな内
容だった場合には失敗する。ファイルの先頭行が<CR>で終わっていてその1行限りの時、
先頭行から<CR>が失われてしまうのでエラーメッセージが出るだろう。
Mac Classic: ":source" で読み込まれるファイルは通常、行末に<CR>を持っている。
これらは常に機能する。もしも行末に<NL>を持つファイルを使っているならば(例えば
UNIXで作られたファイル)、'fileformats' が空でなくかつ先頭行が<CR>で終わってな
ければ正しく認識される。先頭行に<CR>を持ち<NL>で改行しているファイルを使用しな
いように気をつけること。
その他のシステムでは、Vimは ":source" で読込まれたファイルの行末は<NL>であるこ
とを期待する。これは常に働く。もしも行末が<CR><NL>であるファイル(例えばMS-
Windowsで作られたファイル)を使っているならば、全ての行が末尾に<CR>を持っている
ことになる。これは幾つかのコマンドにとって問題となるだろう(例、マッピング)。自
動的に行末記号を検出する機構はない。なぜなら<CR>で終了するマッピングの定義を
ファイルの先頭に書くことは一般的で、自動検出用の仕組みを作るのが難しいからであ
る。
line-continuation
":source" で読込まれたExコマンドスクリプトのファイル内の長い行は、行継続記号
"\" (backslash) を次行の先頭に挿入することで分割できる。バックスラッシュの前に
空白を挿入することも可能で、これらは無視される。
例: 次の記述は
:set comments=sr:/*,mb:*,el:*/,
\://,
\b:#,
\:%,
\n:>,
\fb:-
\://,
\b:#,
\:%,
\n:>,
\fb:-
次の1行と同じ意味として解釈される:
:set comments=sr:/*,mb:*,el:*/,://,b:#,:%,n:>,fb:-
バックスラッシュの前に先行する空白文字は全部無視される。しかしながらバックス
ラッシュのある行の1つ前の行末には、自由に空白文字を挿入することはできない; 付
加的な空白文字が許されるかどうかは、コマンドが分割される位置に依存する。
スペースが必要な場合には、バックスラッシュの直後に書くのがベストである。行末に
スペースを書くと、視認が難しく、誤って削除されてしまうかもしれない。
:syn match Comment
\ "very long regexp"
\ keepend
\ "very long regexp"
\ keepend
":append" と ":insert" コマンドには1つ問題がある:
:1append
\asdf
.
バックスラッシュは行継続シンボルに見えるが、コマンドの結果はこのようになる:\asdf
.
:1appendasdf
.
これを避けるには、'cpoptions' に 'C' フラグを追加することだ:.
:set cpo+=C
:function Foo()
:1append
\asdf
:.
:set cpo-=C
:function Foo()
:1append
\asdf
:.
:set cpo-=C
Note 関数の中でその手のコマンドを実行するには、関数定義の際に 'C' フラグを追加
する必要があり、それが実行される際にではない。
:set cpo+=C
:function Foo()
:1append
\asdf
.
:endfunction
:set cpo-=C
:function Foo()
:1append
\asdf
.
:endfunction
:set cpo-=C
line-continuation-comment
継続行の間にコメントを追加するには、行を '"\ ' で始める。バックスラッシュの後の
スペースに注意すること。例:
let array = [
"\ first entry comment
\ 'first',
"\ second entry comment
\ 'second',
\ ]
"\ first entry comment
\ 'first',
"\ second entry comment
\ 'second',
\ ]
解説:
多くのプログラムは行継続を、継続する行の末尾にバックスラッシュを置くこ
とで表現する。その方法をVimで採用してしまうと、Viとの互換性に重大な欠
陥ができてしまう。たとえばこのようなViのマッピングを考えるとわかりやす
い:
:map xx asdf\
従って一般的ではないが行頭のバックスラッシュを採用している。継続行の中でコメントを開始すると、後続のすべての行がコメントの一部にな
る。それは長い間このようなものだったので、継続行のシーケンスの途中でコ
メントを追加しようとしたとき、\" は有効な継続行であるため、それを使用
することはできなかった。'"\ ' を使用すると最も近いものになるが、少し奇
妙に見えるかもしれない。バックスラッシュの後にスペースを必要とすること
は、これが通常のコメント行にはとても見えないようにするためである。
==============================================================================
5. Vimパッケージを使う packages
Vim script のパッケージは1つかそれ以上のプラグインを含むディレクトリである。
通常のプラグインと比べた長所は以下の通りである:
- パッケージは圧縮ファイルとしてダウンロードでき、独自のディレクトリに展開され
る。よってそのファイルは他のプラグインと混在することがない。これは更新と削除
を簡素化する。
- パッケージには git, mercurial などのリポジトリも使用可能。これはとても更新を
簡素化する。
- パッケージはお互いに依存する複数のプラグインを含むことができる。
- パッケージは起動時に自動的に読み込まれるプラグインと、必要になった時のみ
:packadd により読み込まれるプラグインを含むことができる。
パッケージの使用と自動読み込み
あなたの Vim 関連のファイルは "~/.vim/" にあるとする。
さらにZIP圧縮ファイル "/tmp/foopack.zip" からパッケージを追加したい場合は以下
の通りである:
% mkdir -p ~/.vim/pack/foo
% cd ~/.vim/pack/foo
% unzip /tmp/foopack.zip
"foo" というディレクトリ名は任意である。あなたのお好きな名前を付けてよい。
今あなたの ~/.vim の下に以下のファイルがあるはずである:
pack/foo/README.txt
pack/foo/start/foobar/plugin/foo.vim
pack/foo/start/foobar/syntax/some.vim
pack/foo/opt/foodebug/plugin/debugger.vim
Vim が起動した時、.vimrcを処理した後、'packpath' に含まれる "pack/*/start" ディ
レクトリの下の全てのディレクトリをスキャンする。最初にそのディレクトリは
'runtimepath' に追加される。次に全てのプラグインがロードされる。
これら2つのステップがどのように役立つかについては、packload-two-steps 参照。
上記の例では "pack/foo/start/foobar/plugin/foo.vim" を見つけて
"~/.vim/pack/foo/start/foobar" を 'runtimepath' に追加する。
もし "foobar" プラグインが作動し 'filetype' を "some" にセットした場合、
'runtimepath' に含まれているため、Vim は上記の syntax/some.vim ファイルを見つ
ける。
もし存在するなら、Vim は ftdetect ファイルもロードする。
Note "pack/foo/opt" 以下のファイルは自動的に読み込まれず、"pack/foo/start" 以
下のファイルのみ読み込まれることに注意すること。"opt" ディレクトリがどのように
使われるかについては下記のpack-addを参照。
パッケージの自動読み込みはプラグインの読み込みを無効化している場合は起こらない。
load-pluginsを参照。
'runtimepath' を更新するためにパッケージを読み込むには:
:packloadall
これはプラグインの読み込みを無効化していても効果がある。自動読み込みは一度だけ行われる。
パッケージに "after" ディレクトリがある場合、そのディレクトリは 'runtimepath'
の末尾に追加される。そのため、そこにあるものは全て後でロードされる。
単一プラグインの使用とその自動読み込み
パッケージでなく単一のプラグインがある場合は、余分なディレクトリ階層を作成する
必要がある。
% mkdir -p ~/.vim/pack/foo/start/foobar
% cd ~/.vim/pack/foo/start/foobar
% unzip /tmp/someplugin.zip
これで、次のファイルが作成される。
pack/foo/start/foobar/plugin/foo.vim
pack/foo/start/foobar/syntax/some.vim
ここから上のように動作する。
任意のプラグイン
pack-add
上記の pack ディレクトリから任意のプラグインをロードするには :packadd コマン
ドを使う:
:packadd foodebug
これは 'packpath' の "pack/*/opt/foodebug" から~/.vim/pack/foo/opt/foodebug/plugin/debugger.vim を見つけ読み込む。
これにより何かしらの条件が満たされる時に実行されるようにできる。例えば、Vim が
ある機能をサポートしているかどうかとか、依存したモノが見つからないとか、そうい
うことに依存させることができる。
このコマンドをあなたの .vimrc に入れることで、起動時に任意のプラグインを読み
込むこともできる。
:packadd! foodebug
余分な "!" は Vim が --noplugin で起動されていれば、プラグインがロードされな
いようにするためである。
パッケージが "opt" ディレクトリしか持たなかったとしても一向に構わない。その場
合、それを使いたいときは(明示的に)読み込む必要がある。
どこに何を置くか
:colorscheme で読み込まれるカラースキームは "pack/*/start" と "pack/*/opt"
の下から探し出されるのでどこにでも置くことができる。たとえば、
".vim/pack/mycolors/opt/dark/colors/very_dark.vim" のように、"pack/*/opt" の下
に置くことをお勧めする。
Filetype プラグインはファイルタイプに複数のプラグインがあり、:packadd でロー
ドするプラグインを選択したいのでない限り "pack/*/start" の下に置く必要がある。
例えば、コンパイラのバージョンに依存する場合:
if foo_compiler_version > 34
packadd foo_new
else
packadd foo_old
endif
packadd foo_new
else
packadd foo_old
endif
"after" ディレクトリはパッケージで使うには十中八九便利ではない。しかし、使用が
禁じられているわけではない。
==============================================================================
6. Vimパッケージを作る package-create
パッケージとして配布する1つ以上のプラグインを記述していることを前提とする。
2つの無関係なプラグインがある場合、2つのパッケージを使用することで、Vimユーザー
はどれを含めてどれを含めないかを選択できるようになる。あるいは、両プラグインを
オプショナルとして1つのパッケージにし、:packadd で望みのプラグインを追加する
ようユーザーに指示することもできる。
パッケージの配布方法を決める。アーカイブを作成することも、リポジトリを使用する
こともできる。より多くのユーザーがアーカイブを使用できるが、新しいバージョンに
更新するのは少し難しくなる。リポジトリは通常、最新の状態に保つことができるが、
"git" のようなプログラムが必要である。github ではリリースを作成すると自動的に
アーカイブが作られるので、あなたは両方を同時に行うことができる。
ディレクトリ構成は次のようになる。
start/foobar/plugin/foo.vim " 常にロードされ、コマンドを定義する
start/foobar/plugin/bar.vim " 常にロードされ、コマンドを定義する
start/foobar/autoload/foo.vim " fooコマンドを使用した時に読み込む
start/foobar/doc/foo.txt " foo.vimのヘルプ
start/foobar/doc/tags " ヘルプタグ
opt/fooextra/plugin/extra.vim " オプションのプラグイン、コマンド定義
opt/fooextra/autoload/extra.vim " extraコマンドを使用した時に読み込む
opt/fooextra/doc/extra.txt " extra.vimのヘルプ
opt/fooextra/doc/tags " ヘルプタグ
start/foobar/plugin/bar.vim " 常にロードされ、コマンドを定義する
start/foobar/autoload/foo.vim " fooコマンドを使用した時に読み込む
start/foobar/doc/foo.txt " foo.vimのヘルプ
start/foobar/doc/tags " ヘルプタグ
opt/fooextra/plugin/extra.vim " オプションのプラグイン、コマンド定義
opt/fooextra/autoload/extra.vim " extraコマンドを使用した時に読み込む
opt/fooextra/doc/extra.txt " extra.vimのヘルプ
opt/fooextra/doc/tags " ヘルプタグ
これにより、ユーザーは次の操作を行うことができる。
ここで "myfoobar" はユーザーが選択できる名前だが、唯一の条件は他のパッケージと
は異なることである。
ドキュメントでは、プラグインの機能について説明し、オプションのプラグインをロー
ドする方法をユーザーに伝える。
:packadd! fooextra
このpackaddコマンドをプラグインの1つに追加して、オプションのプラグインが必要な
ときに実行することができる。
:helptags コマンドを実行して、doc/tags ファイルを生成する。この生成されたファ
イルをパッケージに含めるということは、パッケージディレクトリにパッケージを落と
すことができ、ヘルプコマンドがすぐに動作することを意味する。プラグインヘルプを
変更した後にコマンドを再実行することを忘れないでほしい。
:helptags path/start/foobar/doc
:helptags path/opt/fooextra/doc
:helptags path/opt/fooextra/doc
プラグイン間の依存関係
packload-two-steps
同じ機能に依存する2つのプラグインがあるとする。共通機能を autoload ディレクト
リに置くことで、自動的に見つかるようにすることができる。あなたのパッケージには
次のファイルがあるとする。
pack/foo/start/one/plugin/one.vim
call foolib#getit()
pack/foo/start/two/plugin/two.vim call foolib#getit()
pack/foo/start/lib/autoload/foolib.vim func foolib#getit()
これは動作する。なぜなら、パッケージをロードすると、プラグインを読み込む前に見
つかったすべてのディレクトリが 'runtimepath' に追加されるからである。
==============================================================================
7. スクリプトのデバッグ debug-scripts
スクリプトの動作を知るためのコードを追加することができるのは当り前として、Vim
はデバッグモードを提供している。これはスクリプトファイルやユーザーファンクショ
ンをステップ実行することやブレークポイントを仕掛けることを可能にする。
NOTE: デバッグモードは未完成である。デバッグはVimの動作に副作用をあたえる。全
てをデバッグするのには使えない。例えば画面がデバッグメッセージで散乱するときな
ど。
デバッグモードの代わりに 'verbose' オプションが使える。大きな値を設定するとVim
の動作についてより詳細なメッセージを得られる。
デバッグモードを開始する debug-mode
デバッグモードを開始するにはこれらの方法のうちどれかを使う:
1. Vimを-D引数付きで起動する:
vim -D file.txt
最初にvimrcを読み込むところからデバッグを開始する。これはVimの起動時に何が起こっているのかを調査するのに便利である。副作用としてVimは初期化が完了する
前に安全のためターミナルモードを切替える。
(WindowsやMacintoshの)GUI専用バージョンではGUIウィンドウを開くとすぐにデバッ
グが開始する。これを早めるにはvimrcファイルに ":gui" と書くこと。
:debug
2. ":debug" を前に付けてコマンドを実行する。そのコマンドを実行する間だけデバッ
グできる。特定のスクリプトファイルやユーザー関数をデバッグするのに便利であ
る。自動コマンドから呼び出されるスクリプトや関数にも便利である。例:
:debug edit test.txt.gz
3. ブレークポイントをソースファイルやユーザーファンクションに設定する。コマン
ドラインから次のようにできる:
vim -c "breakadd file */explorer.vim"
これはVimを起動して "explorer.vim" の最初の行を読み込むところで停止する。デバッグモード中でもブレークポイントを設定できる。
デバッグモード中に実行されるコマンドはそれが実行される前に表示される。コメント
や空の行、実行されない行は飛ばされる。行が "|" を使って二つのコマンドを含んで
いた場合には分けて表示される。
デバッグモード
--------------
デバッグモードに入ると、通常のExコマンドが使える。例えば、変数の値を見るには:
echo idx
ユーザーファンクション内では、これはローカル変数の "idx" を表示する。"g:" を頭に付けるとグローバル変数の値を表示する:
echo g:idx
全てのコマンドは実行中の関数やスクリプトの文脈として実行される。オプションを設定することもできる。例えば何が起こっているのかを表示するために 'verbose' を設
定することができる。興味のある部分を実行する前に次のようにするといいだろう:
:set verbose=20
スクリーンの更新を必要とするコマンドは避けるべきである。なぜならデバッグモード
を抜けるまでその作用に気づき難いからである。例えば:
:help
これはとても不便である。デバッグモードのためのコマンドラインヒストリが別に用意されている。
NOTE: Vim9 script で、コマンドがスクリプトレベルで記述され次行へ継続するにあ
たって、旧来のバックスラッシュを使わずに行継続されるときは、最初の行のみデバッ
グ出力に表示される。
関数の行番号はその関数の始まりから数える。見ている行の番号を数えるのに苦労する
場合はその関数の書かれたファイルを別のVimで開き、その関数の始まりを探しだし、
"99j" を実行すること。"99" は実際の行番号に合わせて変えること。
さらに、以下のコマンドが使える:
>cont
cont 次のブレークポイントまで実行する。
>quit
quit 異常停止する。これはCTRL-Cを使うことに似ているが、全て
を停止するわけではない。次のブレークポイントで停止す
る。
>next
next コマンドを実行しそれが終わるとデバッグモードに戻る。
ユーザー関数やソースファイルの呼び出し時には呼び出し元
の次の行に進む。
>step
step コマンドを実行しそれが終わるとデバッグモードに戻る。
ユーザー関数やソースファイルの呼び出し時には呼び出し先
の行に進む。
>interrupt
interrupt CTRL-C を使うことに似ているが、次のコマンドを実行する
ためにデバッグモードに戻る場所が ">quit" と違う。例外
割り込みについて:finallyや:catchをテストするのに便
利である。
>finish
finish 実行中のスクリプトやユーザー関数を終了し呼び出し元でデ
バッグモードに戻る。
>bt
>backtrace
>where
backtrace 現在のデバッグセッションの呼び出しスタックトレースを表
bt 示する。
where
>frame
frame N N 番目のスタックフレームへ移動する。+ や - 記号で、相
対的に移動できる。例えば、":frame +3" で 3 つ上のス
タックフレームへ移動する。
>up
up 呼び出しスタックトレースを 1 つ上へ移動する。
>down
down 呼び出しスタックトレースを 1 つ下へ移動する。
デバッグモードのコマンドについて:
- 補完はできない。通常のExコマンドのみ補完できる。
- コマンド名は、他のコマンドが同じ文字で始まらない限り 1 文字まで省略できる。
"f" は "finish" になるので "frame" を省略するには "fr" を用いる。
- <CR>を押すと前回のものを繰り返す。関係ないコマンドを使うとリセットされる
(どうすべきかがわかりにくいため)。
- 同じ名前のExコマンドを使うにはコロンを付けること:
":cont", ":next", ":finish" (省略時も)
vim9-debug
コンパイル済みの :def 関数をデバッグする場合、"step" はすべての命令ではなく、
実行されるすべての行の前で停止する。これにより、ほとんどの場合は非コンパイル関
数のように動作する。ローカル変数へのアクセスは制限されているが可能である:
echo varname
しかし他にはあまりない。特定のバイトコード命令ではなく、通常のExコマンドのように実行されるコマンドを実
行する場合、"step" はローカル変数を検査できるコンパイル済みコンテキストで1回、
そしてコマンドを実行する直前に1回停止する。
バックトレースは、関数呼び出しの階層を表示する。例えば:
>bt
3 function One[3]
2 Two[3]
->1 Three[3]
0 Four
行 1: let four = 4
"->" は現在いるフレームを指す。"up"、"down"、"frame N" を使うことで、別のフレー
ムを選択できる。
現在いるフレームの、その関数内でのローカル変数にアクセスできる。現在いるフレー
ムの、現在行の内容を表示する方法はまだない。
ブレークポイントの定義
----------------------
:breaka :breakadd
:breaka[dd] func [lnum] {name}
関数にブレークポイントを設定する。例:
:breakadd func Explore
関数名が妥当かどうか検査しないので、関数定義の前にブレークポイントを定義できる。
:breaka[dd] file [lnum] {name}
ソースファイルにブレークポイントを設定する。例:
:breakadd file 43 .vimrc
:breaka[dd] here
カレントファイルのカレント行にブレークポイントを設定する。
次を行うのと同様である:
:breakadd file <cursor-line> <current-file>
Note これはファイルを読み込むときに実行されるコマンドに対してだけ働く。そのファイル中で定義される関数に対しては働かない。
:breaka[dd] expr {expression}
{expression} の評価結果が異なる値となるときに常にブレークする
ブレークポイントを設定する。例:
:breakadd expr g:lnum
これはグローバル変数の lnum が変化するときに常にブレークする。評価中のエラーは抑制されるので、まだ存在しない変数の名前が使え
る。これはまた、式に間違いがあっても何も気付けないということで
もある。
Note: script-variable を監視する場合、スクリプトが切り替わっ
たときにブレークする。これは、定義されたスクリプト内でのみ、そ
のスクリプト変数が有効だからである。そしてそのスクリプトがいく
つかのその他のスクリプトから呼び出される場合、その特定の変数が
可視となったとき、もしくは再度アクセス不能となったときに常に停
止する。
[lnum] はブレークポイントにする行番号である。Vimはその行かそれ以降で停止する。
省略時すると1行目になる。
:debug-name
{name} はファイル名や関数名のパターンである。パターンは自動コマンドで使われる
ものと同じである。完全に一致しなければならない (パターンが "^" で始まって"$"
で終わるように)。"*" は全ての文字列に一致する。'ignorecase' は使われないが、大
文字と小文字を区別しないために "\c" を使うことができる/\c。関数名には()を付
けないように!
ソースファイル名のパターン検査はファイルのフルネームに対して行われる。例:
breakadd file explorer
パスが間違っているので一致しない。 breakadd file *explorer.vim
".../plugin/explorer.vim" と ".../plugin/iexplorer.vim" に一致する。 breakadd file */explorer.vim
".../plugin/explorer.vim" だけに一致する。関数名のパターン検査は ":function" で表示される名前に対して行われる。しかしな
がら、ローカル関数ではスクリプトのIDを知らずともスクリプトローカル関数との照合
が容易にできるようにスクリプト固有の "<SNR>99_" のような接頭辞は無視される。
Note 関数はまず読み込まれ、後で実行される。読み込まれたときに "file" ブレーク
ポイントがチェックされ、実行されるときに "func" ブレークポイントがチェックされ
る。
ブレークポイントの削除
----------------------
:breakd :breakdel E161
:breakd[el] {nr}
ブレークポイント{nr}を削除する。:breaklistを使って番号を確認
できる。
:breakd[el] *
すべてのブレークポイントを削除する。
:breakd[el] func [lnum] {name}
関数内のブレークポイントを削除する。
:breakd[el] file [lnum] {name}
ソースファイル内のブレークポイントを削除する。
:breakd[el] here
カレントファイルのカレント行のブレークポイントを削除する。
[lnum] が省略されると関数、またはファイルの最初のブレークポイントが削除される。
{name} は ":breakadd" で使った名前と完全に同じでなければならない。"explorer"
と "*explorer.vim"、"*explorer*" は違う。
ブレークポイントを列挙する
--------------------------
:breakl :breaklist
:breakl[ist]
全てのブレークポイントを列挙する。
その他
------
:debugg :debuggreedy
:debugg[reedy]
デバッグモードのコマンドをユーザーから直接得るのではなく標準入
力から読み込む。スクリプトのテストのときに便利である。
例:
echo 'q^Mq' | vim -e -s -c debuggreedy -c 'breakadd file script.vim' -S script.vim
:0debugg[reedy]
":debuggreedy" を取り消す。それ以降のデバッグモードコマンドを
使わず、ユーザーから直接デバッグモードコマンドを受け取る。
==============================================================================
8. プロファイリング profile profiling
プロファイリングとは、関数やスクリプトの実行にかかる時間を計測することである。
これを行うには +profile 機能が必要である。
この機能は "huge" 機能つきでコンパイルしたときに含まれる。
また、関数 reltime() を使っても時間を計測できる。この関数には +reltime 機
能だけが必要である。これは "huge" 以外の多くのビルドについてくる。
シンタックスハイライトのプロファイリングについては :syntime を参照せよ。
例えば、one_script.vim スクリプトファイルをプロファイリングするには:
:profile start /tmp/one_script_profile
:profile file one_script.vim
:source one_script.vim
:exit
:profile file one_script.vim
:source one_script.vim
:exit
:prof[ile] start {fname} :prof :profile E750
プロファイリングを開始し、終了時に出力を {fname} に出力する。
{fname} 中の "~/" や環境変数は展開される。
{fname} がすでに存在するときは、警告なしに上書きされる。
変数 v:profiling に 1 が代入される。
:prof[ile] pause
次の ":profile continue" が実行されるまでプロファイリングをし
ない。カウントされるべきでない何かを行う時に使うことができる
(例えば外部コマンドなど)。ネストすることはできない。
:prof[ile] continue
":profile pause" の後にこれを実行すると、プロファイリングを再
開する。
:prof[ile] func {pattern}
パターン {pattern} にマッチする関数をプロファイリングする。
{pattern} がどう使われるかは :debug-name を参照。
:prof[ile][!] file {pattern}
パターン {pattern} にマッチするスクリプトファイルをプロファイ
リングする。
{pattern} がどう使われるかは :debug-name を参照。
このコマンドはスクリプトそのものをプロファイリングするだけで、
その中で定義されている関数のプロファイリングは行わない。
[!] がつけられたときは、そのスクリプト中で定義されている全ての
関数のプロファイリングも行う。
Note スクリプトがこのコマンドの後で読み込まれたときだけ、その
プロファイリングは始まる。スクリプト自身にある :profile コマン
ドは働かない。
:profd[el] ... :profd :profdel
指定された引数に対するプロファイリングを停止する。引数について
は :breakdel を参照。
最初は常に ":profile start fname" コマンドで始めなければならない。結果のファイ
ルは Vim が終了するときに書き出される。例えば、特定の1つの関数のプロファイルな
らば:
profile start /tmp/vimprofile
profile func MyFunc
profile func MyFunc
次に出力の例を挙げる。説明のために行番号が行頭についている:
1 FUNCTION Test2()
2 Called 1 time
3 Total time: 0.155251
4 Self time: 0.002006
5
6 count total (s) self (s)
7 9 0.000096 for i in range(8)
8 8 0.153655 0.000410 call Test3()
9 8 0.000070 endfor
10 " Ask a question
11 1 0.001341 echo input("give me an answer: ")
ヘッダー (1行目から4行目) は関数全体にかかった時間を示している。"Total" はこの
関数を実行している間に経過した時間である。"Self" は "Total" のうち、次のことに
かかった時間を引いたものである:
- 他のユーザー定義関数
- スクリプトの読み込み
- 自動コマンドの実行
- 外部(シェル)プログラム
7行目から11行目は各実行行にかかった時間を示している。実行されない行はカウント
されない。それゆえ、コメント行は決してカウントされない。
Count の桁はその行が何回実行されたかを示す。7行目の "for" コマンドはそれ以下の
行と同様に何回も実行されることに注意すること。これは、ループの終わりを検出する
ためにこの行が何回も実行されるためである。
ユーザー入力待ちにかかった時間は一切カウントされない。それゆえ、input() のプロ
ンプトに反応するのにどれだけ時間がかかろうとも無関係である。
プロファイリングはどこで時間が費やされたかのよい指標を与えてくれるが、多くの
原因によりその結果がごまかされてしまう場合があるということを覚えておくように:
- システム関数 gettimeofday() に依存する時間計測の精度。たとえ時間がマイクロ秒
で表示されていたとしても、1/100秒の精度しかないこともある。
- 実経過時間が計測される。他のプロセスがビジーであると、それが予測できない箇
所で遅れを引き起こす可能性がある。
- 1行に複数のコマンドを書いていると、1つの時間しか得られない。ここのコマンド
に対して時間を見るにはその行を分割すること。
- 各行の時間の総和をとると、たいてい関数全体の時間より小さくなる。各行の間に
オーバーヘッドがある。
- Vim が終了する前に削除された関数はプロファイリング情報を生成しない。必要な
ら変数 v:profiling をチェックすること:
:if !v:profiling
: delfunc MyFunc
:endif
: delfunc MyFunc
:endif
- マルチプロセッサーシステム上では、スリープモードが作動したときや、省力のため
プロセッサーの周波数が下がったとき、プロファイリングが奇妙な結果を出すかもし
れない。
- 関数が再帰的に呼ばれた場合、"self" 時間は正しくない。
vim:tw=78:ts=8:noet:ft=help:norl: