lexima.vimとasyncomplete.vimのキーバインドにハマった話

vim

先日、vim.jp でauto-pairs のプラグインでハマった部分の解決策を教えてもらった

そのときにlexima.vimを勧めてもらったので試していたが、キーバインド周りで詰まったのでまとめておく。

何が起きたか

  • asyncomplete の補完表示中のキーバインドが意図した挙動をしない。
  • 上記の問題が時折起こる(毎回起こるわけではない)

私はdein.vimhook_add でキーバインドを以下のように設定している。

hook_add = """
inoremap <expr> <C-j> pumvisible() ? "\<C-n>" : "\<C-j>"
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <C-k> pumvisible() ? "\<C-p>" : "\<C-k>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<CR>"
imap <C-space> <Plug>(asyncomplete_force_refresh)
let g:asyncomplete_auto_completeopt = 1
let g:asyncomplete_matchfuzzy = 1
let g:asyncomplete_auto_popup = 1
"""

補完表示が出ているときに <Tab> を押すと補完の選択、<CR> で確定のバインドをしている。

しかし、lexima.vim を導入した後、時折このバインドが発動せずに通常の <Tab>,<CR> の挙動をすることが起きるようになった。

かつ、この挙動が起きない時(正常に動いているように見える時)には leximainput_after の挙動がうまくいかないように見えた。

(|)
[`|`の位置で<CR>を入力すると]
(
|
)

調べた内容

  • 何がトリガになっているか
    • <CR> にバインドされているものは leximaasyncomplete だけ
  • どのような状況で起こるのか
    • dein.tomlhook_addecho を仕込んで読み込み順序を確認した

これらをやったところ、どうやら asyncomplete -> lexima の順に読み込むと補完のバインドがおかしくなることがわかった。
また、lexima の issue を見ると、同様の issueがあった。

この issue は asyncomplete ではなさそうだが、同様に <CR> のバインドがうまくできないようだ。

解決策

  • 読み込み順序を指定する
    asyncomplete のプラグイン設定を dein_lazy.toml に移動し、on_source オプションで lexima.vim を読み込んだ後に読み込むように変更した。
    また、<CR>lexima の評価を混ぜるように変更した。
[[plugins]]
hook_add = """
inoremap <expr> <C-j> pumvisible() ? "\<C-n>" : "\<C-j>"
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : lexima#expand("<LT>Tab>","i")
inoremap <expr> <C-k> pumvisible() ? "\<C-p>" : "\<C-k>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <CR> pumvisible() ? "\<C-y>" : lexima#expand("<LT>CR>", "i")
imap <C-space> <Plug>(asyncomplete_force_refresh)
let g:asyncomplete_auto_completeopt = 1
let g:asyncomplete_matchfuzzy = 1
let g:asyncomplete_auto_popup = 1
"""
repo = "prabirshrestha/asyncomplete.vim"
depends = "lexima.vim"
on_source = "lexima.vim" # if load this binding before loading lexima, override this bindings by lexima's and not work fine.

個人的には asyncomplete の設定に lexima の関数が出てくるのが気に食わないが、dependslexima を指定しているので妥協できる。
deindepends の仕様がよくわかっていない。指定するだけでは読み込まず、別途 [[plugins]] しなければならないことは知っているが…)