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)を返し、引数に 1
か 0
を渡すと 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 のオンオフを切り替える ImeOff
と ImeOn
というユーザー定義コマンドを作成し、それをインサートモードに入ったとき(autocmd InsertEnter
)とインサートモードを抜けるとき(autocmd InsertLeave
)に ImeAutoOn()
, ImeAutoOff()
関数経由で実行しています。
ImeAutoOff
関数では let b:ime_status=system('spzenhan.exe')
で spzenhan.exe を引数無しで実行して IME の状態を取得して変数に格納しています。この変数を ImeAutoOn
関数で使用することで、インサートモードを抜けるときの IME の状態を復元しています。