はじめに
この記事ではVSCode + Neovim + Google日本語入力の組み合わせで発生する、挿入モード初回の日本語入力が二重入力される&後続の文字が消えるというバグを完全に回避できた方法を紹介します。
なお、本記事で扱う「VSCode Neovim」とは、VSCode上でNeovimを動作させるプラグイン及びそれを利用した環境を指します。
この環境ではNeovim本体の設定がそのまま反映されるためVSCode上でもNeovimと同じ操作感で作業できます。
筆者の環境は以下の通り:
-
macOS(Apple Silicon)
-
VSCode(VSCode Neovimプラグイン使用)
-
Neovim(設定ファイルはinit.lua)
-
Google日本語入力
-
im-select(IME制御ツール)を導入済み
使用していたIME切替の設定
もともと筆者はVim操作性を向上させるために以下のような設定を導入していました
-
ノーマルモードに戻ると、現在の入力ソース(日本語 or 英数字)を記憶し、英数字に強制切替。
-
再び挿入モードに入ると、直前の入力ソースを自動で復元。
-- Google日本語入力でのIM復元対応版
local input_english = 'com.google.inputmethod.Japanese.Roman'
local input_japanese = 'com.google.inputmethod.Japanese.base'
_G.saved_input_source = nil
vim.api.nvim_create_autocmd('ModeChanged', {
pattern = 'i:*',
callback = function()
local current = vim.fn.system('/opt/homebrew/bin/im-select'):gsub('%s+', '')
_G.saved_input_source = current
vim.fn.system('/opt/homebrew/bin/im-select ' .. input_english)
end,
})
vim.api.nvim_create_autocmd('InsertEnter', {
callback = function()
if _G.saved_input_source and _G.saved_input_source ~= input_english then
vim.defer_fn(function()
vim.fn.system('/opt/homebrew/bin/im-select ' .. _G.saved_input_source)
end, 10)
end
end,
})
この設定は長らく安定して動作していました。
突如発生したバグ:日本語初回入力が二重になる
ところがある日突然以下のような挙動が発生するようになりました。
-
挿入モードに入り、日本語入力で「あ」と打つと「ああ」になる
-
しかもカーソルの後ろにあった文字が上書きされて消える
入力ミスだけでなく文字が勝手に消えるため非常にストレスの多いバグでした。
なお、これはNeovim単体では発生せずVSCode Neovim環境に限って再現しました。
また、この事象は i での挿入モードへの移行時にのみ発生し、I や a、A、o、O などのコマンドでは発生しませんでした。
設定ファイルを見直しても改善せず
-
im-select
の遅延時間を変更 → 再現 -
入力ソースの自動復元を無効化(IME制御部分のみ削除) → 再現
-
手動で日本語に切り替えてみる → 再現
-
init.luaの内容をまるごと全削除 → 再現
-
Mac本体再起動 → 再現
つまり自動切替などの設定とは無関係に、VSCode NeovimとIMEの相性に起因する問題のようでした。
回避策の発見:ワンアクション入れるとバグらない
いろいろ試行錯誤する中で、
挿入モードに入った直後に一度スペースを入力してから文字を入力すればバグが起きない
という挙動に気づきました。
どうやらIMEが初回の入力を正しく扱うためには何らかの仮入力が必要なようです。
最終的な解決策
VSCode NeovimでのInsertEnter時にスペースとバックスペースを送信することでこのバグは完全に回避できました。
以下の設定を追加することでこの処理を自動化できます。
-- VSCode-Neovim のときだけ実行(Neovim単体では不要)
if vim.g.vscode then
vim.api.nvim_create_autocmd('InsertEnter', {
callback = function()
vim.defer_fn(function()
-- スペースキーを1回入力してすぐ削除(日本語入力バグ回避用)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<Space><BS>', true, false, true), 'n', false)
end, 10)
end,
})
end
10msの遅延を入れることでIMEの内部処理とぶつかるのを避けることができます。
結果
-
初回の日本語入力でも二重にならない
-
上書きされない
-
IME復元との併用も可能
体感的にも違和感ゼロで快適なVSCode Neovimライフが戻ってきました。
まとめ
このように一見Neovimの不具合や設定ミスに思える現象でも実はVSCodeやIMEとの相性、あるいは仕様変更の影響が絡んでいる場合もあります。
今回紹介した方法は少なくとも筆者の環境では確実に再現・回避が可能だったので、同様の問題(日本語がダブる/文字が消える)に悩まされている方の助けになれば幸いです。
最近のVSCodeのアップデート以降似たような症状を報告する声も散見されるため、Google日本語入力だけに限らない可能性もありそうです。