WSL2 + Neovim + VSCode でIME の状態を制御する方法

前置き

これまでいくつかのエディタを使ってきましたが、Vim のキーバインドが使えると何かと楽、というよりも Vim のキーバインドに手が慣れているため、思い切って Neovim を使ってみることにしました。

ただ、必要に応じて VSCode も使えるようにしたいので、VSCode のプラグインの vscode-neovim/vscode-neovim: Vim-mode for VS Code using embedded Neovim もインストールして、VSCode と Neovim を統合することにしました。

そのために現在進行形で色々と設定していますので、備忘録として設定内容をメモしていきます。

今回実現したいこと

インサートモードでの IME の状態を記憶しておいて、ノーマルモードに戻ってから再度インサートモードに入ったときに、従前の IME の状態を復元するというものです。

つまり、インサートモードで IME をオンにして日本語を編集し、そこから esc キーでノーマルモードに戻ったら IME をオフにしてキー操作に備え、再びインサートモードに入ったら IME の状態を復元(=IME オン)するというものです。

この機能を実現したい理由は、私がエディタで編集する文書の多くが日本語の文章なので、インサートモードで選択した IME の状態を、再びインサートモードに入ったときに復元できると作業効率が大幅にアップするためです。

ノーマルモードに戻ったときに IME を自動的にオフにする方法はすぐに見つかったのですが、インサートモードで選択していた IME の状態を復元する方法は中々見つからなかったため、その方法をメモします。

環境

1# Powershell
2$ wsl --version
3WSL バージョン: 1.0.3.0
4カーネル バージョン: 5.15.79.1
5WSLg バージョン: 1.0.47
6MSRDC バージョン: 1.2.3575
7Direct3D バージョン: 1.606.4
8DXCore バージョン: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
9Windowsバージョン: 10.0.22621.900
 1# WSL2
 2$ lsb_release -a
 3No LSB modules are available.
 4Distributor ID: Ubuntu
 5Description:    Ubuntu 20.04.5 LTS
 6Release:        20.04
 7Codename:       focal
 8
 9$ nvim --version
10NVIM v0.8.1
11Build type: Release
12LuaJIT 2.1.0-beta3
13Compiled by linuxbrew@43b3775c8372

使った外部ツール

Neovim 自体に IME の状態取得や切り替え機能は備わっていませんので、IME の状態取得や切り替えは外部ツールを使う必要があります。

私が使ったのは kaz399/spzenhan.vim というツールです。このツールは、引数無しで実行すると IME の状態(IME ON → 1, IME OFF → 0)を返し、引数に 10 を渡すと IME をオン・オフしてくれるというものです。

このツールは iuchim/zenhan から Fork して開発されたツールですが、zenhan が備えている IME の切り替え機能に現在の IME の状態を取得する機能が追加されているため、今回採用しました。

手順

ツールのインストール

まず、git clone [git@github.com](mailto:git@github.com):kaz399/spzenhan.vim.git コマンドで spzenhan.vim をインストールします。

パスの設定

私はシェルに fish を使っているため、 set -Ux fish_user_paths $HOME/spzenhan.vim/zenhan/ $fish_user_paths コマンドでツールへのパスを通しました。これで spzenhan.exe コマンドで IME の状態取得や制御ができるようになります。使用結果は次のとおりです。

1# IME ON の時
2$ spzenhan.exe
31
4# IME Off の時
5$ spzenhan.exe
60
7
8$ spzenhan.exe 1 # IME Off -> On
9$ spzenhan.exe 0 # IME On -> Off

init.vim の設定

以下のコードを init.vim に追加します。

 1" IME制御の設定
 2command! ImeOff silent !spzenhan.exe 0
 3command! ImeOn  silent !spzenhan.exe 1
 4
 5function! ImeAutoOn()
 6    if !exists('b:ime_status')
 7        let b:ime_status=0
 8    endif
 9    if b:ime_status==1
10        :silent ImeOn
11    endif
12endfunction
13
14function! ImeAutoOff()
15    let b:ime_status=system('spzenhan.exe')
16    :silent ImeOff
17endfunction
18
19" IME off when in insert mode
20augroup InsertHook
21    autocmd!
22    autocmd InsertEnter * call ImeAutoOn()
23    autocmd InsertLeave * call ImeAutoOff()
24augroup END

コードの内容を解説しますと、command! で IME のオンオフを切り替える ImeOffImeOn というユーザー定義コマンドを作成し、それをインサートモードに入ったとき(autocmd InsertEnter)とインサートモードを抜けるとき(autocmd InsertLeave)に ImeAutoOn(), ImeAutoOff() 関数経由で実行しています。

ImeAutoOff 関数では let b:ime_status=system('spzenhan.exe') で spzenhan.exe を引数無しで実行して IME の状態を取得して変数に格納しています。この変数を ImeAutoOn 関数で使用することで、インサートモードを抜けるときの IME の状態を復元しています。


参考にしたサイト