Vimでファイルとvimrcを再読み込みする(:e! / :source)
別プロセスがログを書き足したり、git checkoutでブランチを切り替えたりすると、Vimが抱えているバッファは古い内容のまま取り残されます。開き直さずに最新化する方法と、同じ「再読み込み」でも意味が違う「vimrcを反映し直す」方法を分けて整理します。どちらも1コマンドで済むのですが、Vimが自動で追随してくれる範囲を誤解しているとハマります。
検証環境:macOS同梱のVim 9.1.1752とNeovim 0.12.4で確認しました。オプションの既定値・エラーメッセージ・autocmdの登録件数はすべて実行結果の実物です。Windows環境では確認していません。
目次(8項目)
| コマンド | これだけ覚える |
|---|---|
:e | 今のバッファをディスクの内容で読み直す |
:e! | 未保存の変更を捨てて強制的に読み直す |
:checktime | 外部で変更されていないか確認させる |
:source $MYVIMRC | 設定ファイルを読み直す |
今のバッファを読み直す
引数なしの:edit(省略形:e)を実行すると、今開いているファイルをディスクから読み直します。
:edit
:e
バッファに未保存の変更があると、この形は拒否されます。手元で変更済みのバッファに対して実行したときのメッセージがこれです。
E37: No write since last change (add ! to override)
書かれているとおり、変更を捨ててよければ末尾に!を付けます。:e!は確認を挟まずにバッファの内容をディスクの内容で上書きするので、残したい編集があるなら先に保存します。
:edit!
:e!
読み直しではundo履歴も切り離されます。:e!の直後にuを押しても読み込み前の編集内容は戻らないので、「間違えたら戻せばいい」という感覚で使うコマンドではありません。
autoreadを入れないと自動では追随しない
外部でファイルが書き換わったとき、Vimが黙って最新内容に差し替えてくれるかどうかは'autoread'オプションで決まります。ここがVimとNeovimで違います。素の状態で読み取った既定値がこれです。
| エディタ | 'autoread'の既定値 | 外部変更の扱い |
|---|---|---|
| Vim 9.1.1752 | 無効 | 警告が出るだけでバッファは古いまま |
| Neovim 0.12.4 | 有効 | 変更が無ければ黙って最新化される |
差が実際に出るところまで確かめました。同じ手順で、バッファを編集していない状態のままファイルを外部から書き換え、:checktimeを実行してバッファの1行目を読み出しています。
set autoread → buffer 1行目=[CHANGED BY OUTSIDE]
set noautoread → buffer 1行目=[original line]
'autoread'が無効だと、Vimは「ファイルが変わっている」と教えるだけで中身は入れ替えません。「設定を入れたのに反映されない」という話の多くはここが原因で、Neovimの記事をそのままVimに持ち込むと噛み合わなくなります。
なお'autoread'が有効でも、バッファ側に未保存の変更があるときは自動では上書きされません。編集内容を勝手に捨てない作りになっていて、この場合は読み直すか変更を保存するかを自分で選ぶことになります。
外部の変更を自動で取り込む
'autoread'は「聞かれたときに答える」だけの設定で、Vimが常時ファイルを監視しているわけではありません。実際にチェックが走るのは:checktimeを実行したときや、コマンドを打つなど何らかの操作をしたタイミングです。ログを開きっぱなしにして眺めたいなら、チェックのきっかけを自分で仕込みます。
set autoread
augroup AutoReload
autocmd!
autocmd FocusGained,BufEnter,CursorHold * silent! checktime
augroup END
set autoreadとautocmdはセットで書く必要があります。checktimeだけ仕込んでも、Vimでは既定が無効なので警告が出るだけで終わります。CursorHoldを入れておくと、キー操作を止めてしばらく経ったときにもチェックが走るので、フォーカスを移さずに眺めているだけの場面でも追随します。
autocmdをaugroupとautocmd!で囲んでいるのは、この設定ファイルを読み直したときに同じautocmdが積み重ならないようにするためです。理由は後述します。
複数のバッファをまとめて読み直す
git checkoutのようにファイルが一斉に変わったときは、1つずつ:e!していられません。:bufdoや:tabdoと組み合わせると一括で処理できます。
:bufdo e! " 開いている全バッファ
:tabdo e! " 全タブページのカレントウインドウ
:windo e! " 現在のタブページの全ウインドウ
ただし:bufdoはバッファリストにある全部が対象なので、未保存の作業を抱えたバッファまで巻き込みます。無関係なファイルを触りたくないときは、対象のバッファへ移動してから個別に実行するほうが安全です。
:ls " バッファ番号を確認する
:buffer 3
:e!
どのバッファに未保存の変更が残っているかは:lsの出力で分かります。+が付いているものが変更ありなので、一括実行の前に眺めておくと事故を減らせます。
vimrcを反映し直す
ここまではファイルの中身の話でしたが、「設定を変えたので反映したい」という意味で再読み込みを探している場合はコマンドが変わります。設定ファイルは:sourceで読み直します。
:source $MYVIMRC " どこからでも設定ファイルを読み直す
:source % " 設定ファイルを編集中ならこれで足りる
:so % " 省略形
$MYVIMRCは、起動時に実際に読み込んだ設定ファイルのパスがVim側で入る変数です。手元で通常起動して中身を確認したところ、Vimでは~/.vimrcのフルパスが入っていました。Neovimでも同じ変数が使えて、こちらはinit.luaのパスが入ります。パスを覚えていなくてもこの1行で済むので、設定をいじりながら試すときに便利です。
注意したいのは、:sourceは設定ファイルをもう一度上から実行するだけで、前回の設定を打ち消してはくれない点です。設定ファイルから削除したsetやキーマッピングは、読み直しても消えずに残ります。設定を消したときの動作を確かめたいなら、素直にVimを再起動するのが確実です。
再sourceでautocmdが二重登録される
「打ち消してくれない」の実害がいちばん分かりやすく出るのがautocmdです。augroupで囲っていない(あるいは囲っていてもautocmd!を書いていない)autocmdは、読み直すたびに増えていきます。実際に同じ設定ファイルを3回:sourceして、登録件数を数えました。
1回source: 2件
2回source: 4件
3回source: 6件
件数が増えるということは、保存するたびに同じ処理が2回3回と走るということです。整形コマンドを仕込んでいると目に見えて遅くなりますし、通知系なら同じメッセージが何度も出ます。augroupの先頭でautocmd!を実行してグループの中身を空にしてから登録し直せば、この問題は起きません。同じ手順で数え直すと件数が変わりませんでした。
augroup MyGroup
autocmd!
autocmd BufWritePost * echo "saved"
augroup END
1回source: 1件
2回source: 1件
3回source: 1件
設定ファイルに書くautocmdは、最初からこの形にしておくのが安全です。どのファイルが読み込まれているかを確認したいときは:scriptnamesが使えます。
ビルドが吐くログをVimで開きっぱなしにしていた頃、FocusGained * checktimeだけ書いて満足していたのですが、まったく更新されずに悩みました。Neovimで動いていた設定をVimに持ってきたのが原因で、set autoreadが抜けていただけでした。もうひとつ、設定をいじりながら:so %を連打していたら保存のたびに整形が3回走るようになったことがあって、これがaugroupとautocmd!を必ず書くようになったきっかけです。数え方を知らないと原因にたどり着けないので、:autocmd BufWritePostで一覧を出す方法は覚えておく価値があります。
まとめ
ファイルの中身を読み直すのは:e、未保存の変更を捨ててよければ:e!です。外部の変更に自動で追随させたいならset autoreadとautocmdのchecktimeをセットで書きます。Vimは'autoread'が既定で無効、Neovimは有効という差があるので、他所の設定をそのまま持ってくると噛み合いません。設定ファイルのほうを反映し直したいときは:source $MYVIMRCですが、これは打ち消しをしないので、autocmdはaugroupとautocmd!で囲っておかないと読み直すたびに増えていきます。