2012年11月14日水曜日

Vimで入力補完を常にオンにするvimrc

どうもー、久々にブログ書きます。
プログラミングを始めたらブログを書きたくなりますね!
自分用のメモですけどね

Vimには入力補完機能があるのですが<C-X><C-P>を押さないと実行できません。
これをわざわざ押さずに、文字が入力されたら常に実行する方法は
autocomplpop.vimもしくはneocomplcache.vimというプラグインを利用します。

でもさあ。。。

よく分からないんだな使い方が。
autoloadフォルダとpluginフォルダにプラグインを突っ込めば動くのは分かるのですが、ちょっと変わったことをしようと思ったらどうすればいいのか(´Д`)

Vimプラグインってマニュアルが少ない気がする・・・日本語の!


そこで、自分で改造しやすくしかもシンプルに自動補完を効かせる方法は、vimrcファイルにこう書くだけでした

set completeopt=menuone
for k in split("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_",'\zs')
  exec "imap <expr> " . k . " pumvisible() ? '" . k . "' : '" . k . "\<C-X>\<C-P>\<C-N>'"
endfor

autocomplpop.vimは結局のところ、これを更に上手いこと調整しているだけのようです。neocomplcache.vimはそもそもVim標準の補完を使っていないのだとか(参照:Hack #44: 自動補完を活用する 前編↗


一応説明をしておくと、
set completeopt=menuone
これは補完候補が一つの場合でもポップアップ表示するオプションです

split("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_",'\zs')
これは文字列を一文字ずつ分割して文字のリストにします。正規表現の'\zs''.\zs\ze.'を今回の場合に最適化した形でして、要するに文字と文字の境界です。

exec ""
これは文字列のコマンドを実行します。もしこうせずに直接"imapを使うと、kという変数がキーとして扱われてしまいます。

"imap " . k . " pumvisible() ? '" . k . "' : '" . k . "\<C-X>\<C-P>\<C-N>'"
これは挿入モードのときに、さっきの文字一つ一つにその文字を入力した後<C-X><C-P>を実行するようにマップします。ただしそれだけだとマッチした補完候補が勝手に入力されてしまうので<C-N>で候補を未選択にします。
pumvisible()関数ですでに補完が開始されていたときに更に補完が開始されることを防ぎます。
<expr>はimapに文字列内のコードをマップするためのものです。これが無いとさっきのpumvisible()pumvisibule()と入力されるだけになってしまいます。
あと、このときのドットは文字列の連結です。


すごく適当な説明ですが、これでアルファベットが入力されたときに補完を開始できます。

え? 日本語?

日本語の補完とかいらなくね?

いらいないよ!いらないことにしよう!

変換候補あるし




あと私はC#を使っているので、とあるタイミングで特別な補完をしたいときがあります。

それはドットが入力されたとき!です

Vimにはオムニ補完というのがあって、各々の言語に特化した補完が利用できます。C#ですとdotnet-complete - vimで.Net(*.cs, *.xaml)の補完機能↗で標準ライブラリのみの補完プラグインを作っている方がいらっしゃいます。

普段は普通の補完を使って、ドットが入力されたときだけオムニ補完を実行できるようには・・・

imap <expr> . pumvisible() ? "\<C-E>.\<C-X>\<C-O>\<C-P>" : ".\<C-X>\<C-O>\<C-P>"

こうだ!

オムニ補完を実行するコマンドは<C-X><C-O>なのでそれを挿入モードのドットにマップします。
すでに通常補完が実行されている可能性があるので、その場合は<C-E>で補完を終了してからオムニ補完を実行します。オムニ補完は通常の補完と仕様が異なるみたいで、勝手に候補が選択されることを防ぐには<C-P>を使います。

ちなみに.csファイルにだけこれを適応するには

au BufNewFile,BufRead *.cs imap <buffer> ....

です





(2012/11/20 追記)

上記のようにしてしばらく使っていたのですが、どうにも改行関係が使いにくいです

補完候補が表示されている状態で、候補を選択せずにEnterキーを押すと、補完候補が消えるだけで改行されません。
また、補完候補を<C-N>や<C-P>で選択した状態で改行を押すと、候補が決定した後でさらに改行が入力されます。

それっておかしーよね

Vimそのものの仕様が変なのでこれはもう仕方ないんですけど、なんとか上手いこと使えるようにならないかなーと色々試してこんなふうになりました。

set completeopt=menuone
for k in split("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_",'\zs')
  exec "imap " . k . " " . k . "<C-N><C-P>"
endfor

imap <expr> <TAB> pumvisible() ? "\<Down>" : "\<Tab>"


文字を入力した後で毎回<C-N><C-P>をしていますが、こうすることで補完候補が表示されている状態でも改行を効かせることができます。なんで?って知らない。いじってたら発見した。
また、候補の選択はTabキーで行なっています。<C-N>と<Down>は仕組みが違ってて、<Down>で選択した状態でEnterキーを押すと改行が入力されずに済みます。

ついでに補完そのものを他バッファも参照するタイプに変えました。そうするとすっきりするので。

0 件のコメント:

コメントを投稿