Vimにプラグインを入れる方法(標準パッケージとvim-plug)
Vimにプラグインを入れるのに、管理ツールは必須ではありません。Vim 8.0から入った「パッケージ」の仕組みがあり、決まった場所にディレクトリを置くだけで起動時に読み込まれます。git cloneを1回打てば終わりです。
ただし、置いただけで動くぶん、読み込まれる順番が見えにくくなります。vimrcにプラグインの設定を書いたのに効かない、という相談の多くはここが原因です。この記事では、ダミーのプラグインと実在のプラグインを置いて、vimrcの中から何が見えて何が見えないのかを実際に確かめた結果を載せます。後半ではvim-plugでも同じ手順を踏み、どちらを選ぶかの目安を書きます。
検証環境:Vim 9.1.1752(macOSの/usr/bin/vim)、NVIM v0.12.4、git 2.42.0。一時ディレクトリをHOMEにしてtmuxの中でVimを起動し、手元の設定が混ざらない状態で確かめました。ダミーのプラグイン(fooとbar)は検証用に自作したもので、実在のプラグインはvim-surroundとvim-commentaryを使いました。vim-plugは2026-10-11時点のmasterのplug.vimです。掲載している出力はすべて実行結果で、一時ディレクトリのパスだけ省略しています。
目次(9項目)
| やりたいこと | これだけ覚える |
|---|---|
| 入れる | ~/.vim/pack/plugins/start/にgit clone |
| 必要なときだけ読む | opt/に置いて:packadd 名前 |
| ヘルプを引けるようにする | :helptags ALL |
| 更新する | そのディレクトリでgit pull |
| 外す | ディレクトリを消す(またはopt/へ移す) |
管理ツール無しで入れられる
まず、使っているVimがパッケージに対応しているかを確かめます。8.0より前のVimや、機能を削ってビルドされたVimでは使えません。
:echo has('packages')
1
1が返れば使えます。Vimがパッケージを探す場所はpackpathオプションが持っていて、macOSの/usr/bin/vimでは次の値でした(HOMEの部分は~に置き換えています)。
:echo &packpath
~/.vim,/usr/share/vim/vimfiles,/usr/share/vim/vim91,/usr/share/vim/vimfiles/after,~/.vim/after
先頭の~/.vimの下にpack/任意の名前/start/プラグイン名/という形でディレクトリを置くのが基本です。真ん中の任意の名前はまとめるための箱で、Vimは中身を区別しません。この記事ではpluginsにしています。vim-surroundなら次の1行で入ります。
git clone --depth 1 https://github.com/tpope/vim-surround ~/.vim/pack/plugins/start/vim-surround
vimrcには何も書きません。Vimを起動し直せば、cs"'のようなvim-surroundの操作がもう使えます。runtimepathとpackpathの違いや、どちらが何を探すのかはVimのランタイムパスを確認する記事で詳しく扱っています。
pack/*/startに置くと起動時に読み込まれる
start/の下に置いたプラグインがいつ読み込まれるかは、:scriptnamesで読み込み順を出すと分かります。ダミーのプラグインfooを置いて起動した直後の出力です。
:scriptnames
1: /usr/share/vim/vimrc
2: ~/.vimrc
3: /usr/share/vim/vim91/plugin/colorresp.vim
4: /usr/share/vim/vim91/plugin/getscriptPlugin.vim
...
19: /usr/share/vim/vim91/plugin/zipPlugin.vim
20: ~/.vim/pack/x/start/foo/plugin/foo.vim
~/.vimrcが2番目、foo.vimはVimに同梱のプラグインをすべて読み終えたあとの20番目です。順番は「vimrc → 同梱プラグイン → start/のプラグイン」で、vimrcのほうが先に終わっています。この順番が次の節の落とし穴につながります。何が読まれていて何が読まれていないかを追うときの:scriptnamesの使い方は、設定ファイルが読み込まれない時に使う:scriptnamesにまとめてあります。
読み込まれるのは各プラグインのplugin/の中の.vimファイルと、ftdetect/です。autoload/やcolors/、doc/は必要になったときに探されます。
vimrcの時点ではまだ読み込まれていない
ダミーのプラグインfooのplugin/foo.vimで、変数・関数・コマンドを1つずつ定義しました。同じパッケージにはautoload/foo.vim(関数foo#greet())とcolors/foocs.vim(カラースキーム)も置いてあります。
" ~/.vim/pack/x/start/foo/plugin/foo.vim
let g:foo_loaded = 1
function! FooHello()
return 'hello from foo'
endfunction
command! FooCmd echo 'FooCmd ran'
vimrcの中からこれらが見えるかをexists()で調べ、結果をリストに貯めておいて起動後に表示しました。最後の1行は、起動が終わった時点(VimEnter)でもう一度調べたものです。
vimrc foo_loaded=0
vimrc FooHello=0
vimrc :FooCmd=0
vimrc foo#greet=autoload greet
vimrc colors_name=foocs
vimrc rtp has foo=0
VimEnter foo_loaded=1
vimrcの中では、plugin/で定義された変数・関数・コマンドはどれも存在しません。runtimepathにもstart/fooはまだ入っていません。起動が終わるとg:foo_loadedは1になるので、プラグインが壊れているわけではなく、単にvimrcの実行が早すぎるだけです。
一方で、colorscheme foocsはvimrcの中で成功し、g:colors_nameがfoocsになりました。意外だったのはfoo#greet()で、runtimepathにまだ入っていないのに呼べています。:help packagesには、:colorschemeとautoloadの関数はpackpathのstart/の下も探す、と書かれています。表にすると次のようになります。
| vimrcの中で | 結果 | 理由 |
|---|---|---|
| プラグインの変数を読む | 無い | plugin/はvimrcの後に読まれる |
| プラグインのコマンドを実行 | E492になる | 同上 |
colorscheme | 効く | packpathのstart/も探す |
autoloadの関数(foo#greet()) | 呼べる | 同上 |
プラグインに渡す設定変数(let g:xxx = 1) | 効く | プラグインが読むのはこの後 |
vimrcの1行目にFooCmdとだけ書いて起動すると、次のエラーが出ます。
Error detected while processing ~/.vimrc:
line 1:
E492: Not an editor command: FooCmd
表の最後の行が実用上いちばん大事です。プラグインの設定は、ほとんどが「読み込まれる前にg:の変数を置いておく」形で書かれています。これはvimrcに書けば間に合います。困るのは、プラグインが定義したコマンドや関数をvimrcの中で直接呼ぶ場合です。
どうしてもvimrcの途中で使いたいなら、手前で:packloadallを実行すると、その場でstart/のプラグインがすべて読み込まれます。
packloadall
" ここから先は start/ のプラグインが読み込み済み
この1行を置いたvimrcでは、直後のexists('g:foo_loaded')が1になりました。もう1つの手は、呼び出しをautocmd VimEnterで起動の最後まで遅らせる方法です。上の検証でも、VimEnterの時点では読み込まれていました。
optと:packaddで必要なときだけ読み込む
start/の代わりにopt/の下に置くと、起動しただけでは読み込まれません。たまにしか使わないプラグインを起動時間から外したいときに使います。~/.vim/pack/x/opt/bar/plugin/bar.vimでg:bar_loadedを定義し、:packaddの前後を比べました。
:echo exists("g:bar_loaded")
0
:packadd bar
:echo exists("g:bar_loaded") (&rtp =~ "opt/bar")
1 1
:packadd barの時点でruntimepathに追加され、plugin/も読み込まれます。引数はopt/の下のディレクトリ名です。
vimrcに書くときは、!の有無で動きが変わります。それぞれを書いたvimrcで、直後の状態と起動後の状態を調べました。
" packadd! bar と書いた場合
after packadd! bar_loaded=0 rtp=1
VimEnter bar_loaded=1
" packadd bar と書いた場合
after packadd bar_loaded=1 rtp=1
packadd!はruntimepathに足すだけで、plugin/はその場では読みません。start/のプラグインと同じく、vimrcの後の読み込みの段階でまとめて読まれます。!なしは、その行で読み込みまで済ませます。vimrcでopt/のプラグインを常に使うならpackadd!が基本で、!なしは「この行より後でプラグインの関数を呼びたい」ときに使います。Vimに同梱されているcommentやhlyankのようなパッケージもこのopt/の形で入っていて、packadd!で有効にします。同梱パッケージの中身はVim 9.2の新機能と、9.1から何が変わったかで紹介しています。
既に入れてあるstart/のプラグインをopt/へ移すだけでも同じことができます。vim-surroundをmvでopt/に移すと、起動直後のexists("g:loaded_surround")は0になり、:packadd vim-surroundの後で1になりました。
ヘルプが引けないときは:helptags ALL
パッケージで入れたプラグインは、:helpがそのままでは引けません。vim-surroundをgit cloneした直後の結果です。
:help surround
E149: Sorry, no help for surround
doc/surround.txtは入っていますが、ヘルプの索引にあたるdoc/tagsがありません。リポジトリにはtagsを含めないのが普通なので、自分で作ります。
:helptags ALL
これでruntimepath上のすべてのdoc/にtagsが作られ、:help surroundでvim-surroundのヘルプが開くようになりました。手元では/usr/share/vimのような書き込めない場所についてのエラーは表示されませんでした。vim-surroundの.gitignoreには/doc/tagsが書かれていて、作ったtagsはgit statusにも出ません。
落とし穴はopt/のプラグインです。:helptags ALLが見るのはruntimepathなので、まだ:packaddしていないopt/のプラグインは対象外になります。opt/bar/doc/bar.txtを置いて試すと、:helptags ALLだけではtagsが作られず、:packadd barの後にもう一度流したら作られました。ディレクトリを指定して:helptags ~/.vim/pack/x/opt/bar/docと書けば、読み込まずに作ることもできます。
更新と削除
パッケージで入れたプラグインは、ただのgitのリポジトリです。更新はそのディレクトリでgit pullするだけです。
cd ~/.vim/pack/plugins/start/vim-surround
git pull
# Already up to date.
数が増えたら、シェルで回します。
for d in ~/.vim/pack/*/*/*/; do git -C "$d" pull --ff-only; done
更新でヘルプが変わったときは、もう一度:helptags ALLを流します。外すときはディレクトリを消すだけです。vimrcに書いた設定変数は残っても害はありませんが、プラグインのコマンドをマッピングから呼んでいる場合はそのマッピングも消しておかないと、押したときにE492になります。いったん止めて様子を見たいだけなら、消さずにopt/へ移すほうが戻しやすいです。
dotfilesをgitで管理しているなら、プラグインをsubmoduleにする方法もあります。dotfilesのリポジトリの中で試した手順です。
# 追加
git submodule add https://github.com/tpope/vim-surround vim/pack/plugins/start/vim-surround
# 全部を最新にする
git submodule update --remote
# 外す
git submodule deinit -f vim/pack/plugins/start/vim-surround
git rm -f vim/pack/plugins/start/vim-surround
git rmの後は.gitmodulesからも該当の節が消えました。ただし.git/modules/の下にはクローンの実体が残るので、容量が気になるなら手で消します。別のPCではgit clone --recursiveでプラグインごと取ってこられるのが利点で、どの版を使っているかもdotfiles側のコミットに記録されます。
vim-plugを使うほうがいい場面
管理ツールの代表がvim-plugです。plug.vimを1ファイル置き、vimrcに入れたいプラグインを並べます。
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
call plug#begin()
Plug 'tpope/vim-surround'
Plug 'tpope/vim-commentary'
call plug#end()
Vimを起動して:PlugInstallを実行すると、~/.vim/plugged/の下に取ってきます。手元の表示はこうでした。
Updated. Elapsed time: 0.707618 sec.
[==]
- Finishing ... Done!
- vim-commentary: Already up to date.
- vim-surround: Already up to date.
入れたばかりなのに「Already up to date.」と出ますが、~/.vim/plugged/には2つとも取ってこられていました。doc/tagsもvim-plugが作るので、:helptagsは要りません。vimrcからPlugの行を消して:PlugCleanを打つと、消すディレクトリを示して確認を求めてきます。
Directories to delete:
- ~/.vim/plugged/vim-commentary/
Delete all directories? (y/N)
yでRemoved 1 directories.と出て、ディレクトリが消えました。:PlugStatusは各プラグインが取ってこられているかを- vim-surround: OKの形で返します。
読み込みの順番は、パッケージと大きくは変わりません。plug#end()の直後にruntimepathを調べるとplugged/vim-surroundは入っていましたが、g:loaded_surroundはまだ0でした。plugin/が読まれるのは、パッケージと同じくvimrcの後です。違いが出るのは遅延読み込みで、Plug 'tpope/vim-commentary', { 'on': 'Commentary' }と書くと、起動直後のg:loaded_commentaryは0、:Commentaryを打った後は1になりました。パッケージで同じことをするには、opt/に置いて自分で:packaddを呼ぶコマンドを書く必要があります。
| 場面 | 向いているもの |
|---|---|
| 入れるのが数本で、更新もたまに | 標準パッケージ |
| サーバーなど追加のファイルを置きたくない | 標準パッケージ |
| 10本を超え、まとめて更新・削除したい | vim-plug |
| コマンドやファイル形式で遅延読み込みしたい | vim-plug |
| 入れるものの一覧をvimrc 1か所で見たい | vim-plug |
vim-plugの利点は、一覧がvimrcに残ることです。別のPCでもplug.vimとvimrcをコピーして:PlugInstallを打てば同じ状態になります。標準パッケージではこの一覧が「pack/の下にあるディレクトリ」なので、submoduleで管理しない限りどこにも書かれません。なお、Neovimにも同じパッケージの仕組みがあり、packpathには~/.local/share/nvim/siteが入っています。0.12からは標準のプラグイン管理vim.packが加わったので、Neovimを使うならNeovim 0.12の標準プラグイン管理 vim.packも選択肢になります。
検証で最初にvimrcへexists('*FooHello')を書いて0が返ってきたとき、置き場所を間違えたのだと思い込み、pack/x/start/foo/plugin/のつづりを3回見直しました。起動後に同じ式を打つと1になるので、パスは合っていたわけです。そのくせ同じvimrcの中でfoo#greet()はあっさり呼べてしまい、しばらく何が基準なのか分からなくなりました。autoloadだけ別扱いだと知ったのは、:help packagesを読み直してからです。
まとめ
Vimのプラグインは、~/.vim/pack/plugins/start/にgit cloneすれば入ります。外すときはディレクトリを消し、止めておきたいときはopt/に移して:packaddで読みます。cloneの後に:helptags ALLを1回流しておくと、:helpでプラグインの説明が引けます。
設定でつまずくのは、plugin/がvimrcより後に読まれる点です。設定変数を置くのは間に合いますが、プラグインのコマンドや関数をvimrcで直接呼ぶと、まだ存在しません。colorschemeとautoloadの関数は例外的に呼べます。それ以外はpackloadallかpackadd(!なし)で前倒しするか、VimEnterまで遅らせます。本数が増えて一覧と遅延読み込みが欲しくなったら、vim-plugに切り替える頃合いです。