【概要】
nvim + coc.nvim環境で、coc.nvim公式のキーマップサンプルにあるように、Tabキーにて補完リストを表示するようにできます。しかし、サンプルコードそのままだとコード保管時にTabキー押下にて補完リストを移動できるものの、補完リストが表示されていない状態でTabキーを押下すると、エラーになるため、エラーの状態と対策を行ったキーマップ(Lua版)について例示解説します。【環境】
Ubuntu | 22.04 LTS |
neovim | 0.10.0-dev (--HEAD) |
coc.nvim | 0.0.82 |
【よくあるエラーの起きる書き方】
その1)
local opts = {silent = true, noremap = true, expr = true,
replace_keycodes = false}
vim.keymap.set("i", "<TAB>", 'coc#pum#visible() ? coc#pum#next(1) : v:lua.check_back_space() ? "<TAB>" : oc#refresh()', opts)
vim.keymap.set("i", "<S-TAB>", [[coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"]], opts)
その2)
inoremap <silent><expr> <TAB>
\ coc#pum#visible() ? coc#pum#next(1):
\ <SID>check_back_space() ? "\<Tab>" :
\ coc#refresh()
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\ <S-TAB>" " "\<C-h>"
inoremap <silent><expr> <c-space> coc#refresh()
まず、その1についてですが、下から2行目の v:lua.check_back_space()でluaのグローバル関数check_back_space()を呼び出そうとしているのですが、関数名が見つからず、グローバル変数自体がnilになってしまい、関数の参照エラーで条件分岐に進めず、よって補完リストが表示されていないときにTabキーを押下したケースも実行されないという状態になります。最初、ここはcheck_back_space()からnilが返ってきているのだと思っていたのですが、いろいろ調べているうちにどうやらそうではないということが分かりました。
次にその2ですが、vim.script表記なので、luaに書き換えると、結局ほぼその1と同じになるため、同様のエラーが発生します。
【修正したキーマップ】
local opts = {silent = true, noremap = true, expr = true,
replace_keycodes = false}
- vim.keymap.set("i", "<TAB>", 'coc#pum#visible() ? oc#pum#next(1) : v:lua.check_back_space() ? "<TAB>" : coc#refresh()', opts)
+ vim.keymap.set("i", "<TAB>", 'coc#pum#visible() ? coc#pum#next(1) : "<Tab>"', opts)
vim.keymap.set("i", "<S-TAB>", [[coc#pum#visible() ? coc#pum#prev(1) : "<C-h>"]], opts)
修正したところは、バックスペースの入力チェックは無くても動作に影響がないため、v:lua.check_back_space() を削除したことと、coc#pum#refresh()も条件に合致しなくなり、削除しても同じく影響がないため削除しています。替わりに、coc#pum#visible() の条件が偽の(つまり補完リストが表示されていない)場合、"<Tab>"でタブ文字を挿入するようにしています。これにより、補完リストはTabキーとShift+Tabキーで順送り/逆送りができるのと、インサートモードで補完リストが表示されていないときにタブ文字の挿入の両方を実現しています。
解説はここまでです。最後までお読みいただき、ありがとうございました。