実践 複数環境で動く .vimrc/.gvimrc

<ins>一部嘘が書いてあったので修正。コメントで教えてくれた @Linda_pp さん、 @thinca さんありがとう。</ins>

この記事は vim advent calendar の 8 日目の記事。

http://qiita.com/advent-calendar/2015/vim

vimconf 2015 でのどっちしゃべるか迷ってしゃべらなかったほうのテーマを書く。
rlhelp.vim は年末にいじるよ…。

ここで書くのは複数環境で動く .vimrc や .gvimrc の書き方であって、それらを複数環境で同期させる方法ではない。これについてはそのうち書くかも。

どうやって環境を切り分けるかというのはわりと出てくるんだけど、どういうときに切り分けたほうがいいか、うまい切り分け方というのはあまりない情報なので自分の設定から引っ張りだしてみる。

- https://raw.githubusercontent.com/januswel/dotfiles/master/.vimrc
- https://raw.githubusercontent.com/januswel/dotfiles/master/.gvimrc

動かしてる環境は次。

- MacVim
    - GUI, term 両方
- Windows Kaoriya 版 gvim
    - GUI のみ
- CentOS vim-enhanced
    - term のみ

.gvimrc
-------

まず GUI 環境向けの設定は .gvimrc に書くようにする。

```vim:.gvimrc
" display & information
set lines=25        " typical
set columns=90      " margin for 'number' and 'foldcolumn'
set cmdheight=1     " MacVim $VIM/gvimrc overwrites my .vimrc settings
set guioptions=c    " show no GUI components

" no way to use a mouse
set mouse=
set nomousefocus
set mousehide

" font
if has('win32')
    " When VL Gothic isn't found in the system, use MS Gothic.
    set guifont=VL_Gothic:h12:cSHIFTJIS,MS_Gothic:h12:cSHIFTJIS
    set linespace=0
elseif has('mac')
    set guifont=VL_Gothic:h16
    set linespace=0
endif

" turn off disabling IM at entering input mode
if exists('&imdisableactivate')
    set noimdisableactivate
endif
```

次のオプションは GUI オンリーではないんだけど term 環境でいじると「ちがうそうじゃない」となるのでこちらに書く。

- 'lines'
- 'columns'

また、ランタイムによっては $VIM/gvimrc で .vimrc の設定を書き換えてしまうものもあるのでそれはさらに .gvimrc で再設定しなおす。この例では 'cmdheight' 。
ここらへんは次のページを参照。

http://qiita.com/janus_wel/items/925feab6bf5d35a42e1e

他は<del>マウスや</del>フォントなど、 GUI ならではの設定が並ぶ。
<ins>'mouse' のみは MS-DOS や xterm なんかの非 GUI 環境でも設定可能らしい。その他の 'mousefocus' 、 'mousehide' は GUI 限定。なのでこっちにまとめてしまう</ins>

フォントは環境によって指定方法が異なるので <kbd>:help setting-guifont</kbd> を読んだり、 <kbd>set guifont?</kbd> して使っているシステムの指定方法を確認するといい。
フォントによっては 1 行の間隔が開きすぎているものもあるのでその場合は 'linespace' に負の数を指定すると行間をつめることができる。

特定のオプションがあるかどうかを exists で調べることができる。上の例だと 'imdisableactivate' オプションがあるかどうか。なぜか 'imdisableactivate' はヘルプにないからオプションがあるかどうかを直で調べるしかないんだよね…。

<ins>'imdisableactivate' のヘルプがないのは MacVim 限定のオプションだかららしい。</ins>


encoding
--------

ここからすべて .vimrc の内容。

基本的に Windows 以外は UTF-8 環境なので 'encoding' を変更する必要はないんだけど Windows だけは cmd.exe が cp932 しか扱えないのでそこらへんをうまくする。

```vim
if has('win32')
    if has('gui_running')
        let &termencoding = &encoding
        set encoding=utf-8
    else
        set encoding=cp932
    endif
endif
```

GUI のことは .gvimrc に書くと言っといてアレなんだけど、 'encoding' に関する設定が分散するのは避けたいので .vimrc 側に集約する。

cmd.exe から vim 起動すると cp932 環境で完結するのである意味楽なんだけど gvim で UTF-8 使ってると <kbd>:!</kbd> ではじまるコマンド打つときにそのままでは文字コードがあわなくて文字化けする。たとえば <kbd>:!mkdir 新しいフォルダ</kbd> とか。

その場合 'termencoding' というオプションがあるのでこれをあわせてやる。 cmd.exe が呼び出されるときに引数を 'encoding' から 'termencoding' に変換して渡してくれる。


クリップボード
--------------

yank 内容をクリップボードと共有する設定。

```vim
if has('gui') || has('xterm_clipboard')
    set clipboard=unnamed
endif
```

has 関数に見慣れない文字列を指定しているけど、これはランタイムが指定した機能を持っているかどうかをチェックしている。

各オプションが使えるかどうかを調べる場合はヘルプを読む。たとえば上の例だと <kbd>:help 'clipboard'</kbd> すると次のようなことが書いてある。

> 			{only in GUI versions or when the |+xterm_clipboard|
> 			feature is included}

<q>only in GUI versions</q> と書いてある場合 <code>has('gui')</code> と書く。
同様に <q>+feature_name feature</q> 云々と書いてある場合 <code>has('feature_name')</code> と書いていく。で、今回は <q>or</q> とも書いてあるので <code>||</code> でつなぐという塩梅。


印刷
----

```vim
if has('printer')
    set printoptions=number:y
    set printheader=%<%t%=page\ %N

    if has('win32')
        set printfont=VL_Gothic:h12:cSHIFTJIS
    endif
endif
```

印刷関連の設定。これも printer 機能があるかどうかを調べてから設定する。

ちなみに手早く目的とする機能を持ったランタイムかどうかを確認するには <kbd>:version</kbd> 。機能一覧が +/- 付きで出てくる。 + が使える / - が使えない。


プラグイン読み込み制御
----------------------

標準でついてくるプラグインをロードさせない、という設定もできる。

```vim
if has('win32')
    " in Windows, processing tar, gzip and zip with vim is non-sense...
    let loaded_gzip = 1
    let loaded_tarPlugin = 1
    let loaded_zipPlugin = 1
else
    " setting for bash (:help sh.vim)
    let is_bash = 1
endif
```

一般的な vim プラグインの作法として特定の変数が定義されていると読み込まない、というものがある。なので標準プラグインなんだけど特にいらないや、という場合 .vimrc で先に該当変数を定義して読み込みを抑止できる。

上の例のそれぞれ詳細は次のヘルプに譲る。

- loaded_gzip
    - <kbd>:help gzip</kbd>
- loaded_tarPlugin
    - <kbd>:help :TarDiff</kbd>
- loaded_zipPlugin
    - <kbd>:help g:zip_zipcmd</kbd>
- is_bash
    - <kbd>:help sh.vim</kbd>


スペルチェック
--------------

特定の機能があるときだけマッピングを有効にする、ということもできる。

```vim
if has('spell') && has('syntax')
    nnoremap <silent><Leader>s :setlocal spell!<CR>:setlocal spell?<CR>
endif
```

<kbd>:setlocal spell</kbd> でそのバッファーだけスペルチェックを有効にできる。このスペルチェックは <kbd>:help 'spell'</kbd> 読むとわかるとおり spell 機能と syntax 機能が必要なのでそのチェックをしている。

<del>スペルチェックは日本語を認識しないので常に有効にすると日本語の下に常に波線が出てしまうのでこうやって必要なときに有効にしている。</del>

<ins>cjk という値を 'spelllang' に設定しておくと CJK 文字をスペルチェック対象外にできる。詳しくは <kbd>:help 'spelllang'</kbd> 参照。</ins> ただ、技術的な文書を書いているとわりと単語がスペルチェックにひっかかるので動的に切り替えられるようにしとく。


まとめ
------

いろいろな環境で動くのが vim の利点ということを kaoriya さんが言っていたけども、実際にいろいろな環境に適応させるにはいろいろな設定が必要なのでみんなでこういう情報共有していきましょう。