テキストエディターにVimを使っています。Vimの標準機能だけであるプラグインが現在インストールされているかの判定方法を記します。
はじめに
Vimで作業を快適にするためにいくつかプラグインをインストールしています。そして,プラグインの機能を有効化するために,その設定を.vimrc
に記述しています。
しかし,プラグイン固有の設定を.vimrc
に記述すると,そのプラグインがインストールされていなければ,変数や関数が未定義であるためエラー となります。
これを回避するために,あるプラグインが現在インストールされているかを判定し,インストールされているときだけそのプラグイン固有の設定を記述する必要があります。
パッケージマネージャーやプラグインマネージャーとよばれるプラグインを管理するためのVimプラグインには,プラグインがインストールされているかを識別する関数が用意されています。
例えば,NeoBundle にはneobundle#is_installed()
が存在し,以下のように記述することでNeoBundleでプラグインを管理できているかどうかを判定できます。
NeoBundleによるプラグインの有無の判定方法
if s:Neobundled('caw.vim')
nmap \c <Plug>(caw:hatpos:toggle)
vmap \c <Plug>(caw:hatpos:toggle)
nmap \C <Plug>(caw:zeropos:uncomment)
vmap \C <Plug>(caw:zeropos:uncomment)
endif
上記の例では,コメントのオン/オフの切り替えプラグインcaw.vim
がインストールされているかどうかを判定し,インストールされていればその設定を行っています。
ただし,この方法には以下2点の問題があります。
パッケージマネージャーを利用したプラグインの有無の判定方法の問題
そのパッケージマネージャーを使っていないと利用できない
そのパッケージマネージャー自体がインストールされているかどうかを判定できない
そのため,できればより汎用的で特定のプラグインの機能に頼らずに,プラグインのインストールの判定を行う必要があります。
方法
この問題を解決するために,Vimの標準機能だけで指定したプラグインがインストールされているかどうかを判定する方法を考案しました。
以下の関数を用意して実現します。
プラグインがインストールされているかの判定方法
"" \brief Check if a plugin is installed.
"" \param[in] plugin Plugin name (direcotry name).
"" \return 1: installed, 0: not installed.
function! s:is_plugin_installed(plugin)
return globpath(&runtimepath, 'pack/*/*/' . a:plugin, 1) != ''
endfunction
処理の流れは以下となります。
s:is_plugin_installed()
の処理の流れ
引数にプラグイン名を指定。
runtimepath
からglobpath
によりpack/<directory>/<start or opt>/
から指定した名前のプラグインを検索。
プラグイン名のディレクトリーが存在すれば,trueを返却し,なければfalseを返却。
Vim 8から搭載されたパッケージ管理機能では,プラグインをpackpath
配下のpack/ディレクトリー/start
またはpack/ディレクトリー/opt
に配置することになっています。globpath()
によりpack/
配下の3階層下のディレクトリーを確認することで,プラグインがインストールされているかを判定しています。
s:is_plugin_installed
関数の利用例は以下となります。
s:is_plugin_istalled()
の.vimrc
での利用例
if has('vim_starting')
if match(&runtimepath, expand('~/.vim')) == -1
set runtimepath& runtimepath+=~/.vim,~/.vim/after
if exists('+packpath')
set packpath& packpath+=~/.vim
endif
endif
endif
"" \brief Check if a plugin is installed.
"" \param[in] plugin Plugin name (direcotry name).
"" \return 1: installed, 0: not installed.
function! s:is_plugin_installed(plugin)
return globpath(&runtimepath, 'pack/*/*/' . a:plugin, 1) != ''
endfunction
if s:is_plugin_installed('vim-mucomplete')
set completeopt& completeopt+=menuone
inoremap <expr> <c-e> mucomplete#popup_exit("\<c-e>")
inoremap <expr> <c-y> mucomplete#popup_exit("\<c-y>")
inoremap <expr> <cr> mucomplete#popup_exit("\<cr>")
set completeopt+=noselect
set completeopt+=noinsert
set shortmess+=c " Shut off completion messages
set belloff+=ctrlg " If Vim beeps during completion
let g:mucomplete#enable_auto_at_startup = 1
endif
この例では,Windowsなどpackpath
に~/.vim
がデフォルトで設定されていない場合に,packpath
に~/.vim
を指定しています。その後,補完プラグインであるvim-mucomplete がインストールされているかを判定し,存在すればその設定を反映させるようにしています。
なお,当初は以下のようにfinddir()
を使ってプラグインのディレクトリーを判定していました。
finddir()
によるプラグインの有無の判定方法
"" \brief Check if a plugin is installed.
"" \param[in] plugin Plugin name (direcotry name).
"" \return 1: installed, 0: not installed.
function! s:is_plugin_installed(plugin)
for path in split(&runtimepath, ',')
if finddir(a:plugin, path . '/**') != ''
return 1
endif
endfor
return 0
endfunction
しかし,finddir()
で'/**'
により再帰的に検索すると時間がかかりVimの起動が遅く なってしまいました。そこで,より速度の速いglobpath()
を採用しました。
まとめ
Vimの標準機能だけでプラグインがインストールされているかの判定方法を解説しました。
Vim 8になってから標準でパッケージ管理機能が実装され,パッケージマネージャーを使わなくてもプラグインを管理できるようになりました。今回のプラグインの判定方法を活用することで,標準の機能だけでもある程度の管理ができます。
依存性を下げ,どこでも動作するような.vimrc
の記述を心がけたいものです。
関連