【FreeBSD】Vim/Neovimで挿入モード遷移時に前回のIME状態をセットする(uim-fep/fcitx)

確認環境

   
PC Thinkpad X1 Carbon 2nd Gen
OS FreeBSD 12.1-RELEASE-p1
Neovim NVIM v0.4.3
CLI IME uim-fep version 1.8.8 / Mozc-2.23.2815.102.00_5
GUI IME fcitx version: 4.2.9.5 / Mozc-2.23.2815.102.00_5

課題

以前の記事で、Normalモード遷移時にIMEを自動でOFFするようにした。

とても快適になった。

しかし、Vimで日本語の文章を書いていると下記の状況になることが多い。

  1. 日本語入力中、でNormalモードへ遷移 (IME ON -> OFF)
  2. Normalモードで何かしら操作実施
  3. 再び挿入モードへ遷移 (IME OFFのまま)
  4. 日本語を入力するため手動でIME OFF -> ON

2.のNormalモード遷移前にIMEがONだった場合は、
4.の挿入モード遷移時に自動でIME ONにしたい。

対策

ここでは、自前のシェルスクリプトとVimスクリプトで対応する。

  1. IME(uim-fep/fcitx)のON/OFF状態取得 (シェルスクリプトの作成)
  2. Vimのモード遷移時の処理追加 (.vimrcの設定)

1. IME(uim-fep/fcitx)のON/OFF状態取得

IMEの状態を取得するシェルスクリプトは以下の通り。

このスクリプトは、下記のような動作をする。

  • IME ONなら標準出力に1を出力
  • IME OFFなら標準出力に0を出力
  • 仮想コンソールで$UIM_GET_FILEが未設定(uim-fep未起動)の場合は、標準出力に0を出力

このシェルスクリプトをVimから呼び出せるように、パスが通ったディレクトリ(1)に保存して、実行権限を追加(chmod +x)しておこう。
1 ... 参考) パスを通す

以降は、シェルスクリプトのファイル名はimestsで保存した想定で説明を行う。

ちょっと注意点

以前の記事同様、Vimが動いている環境が仮想コンソール上なのかXウィンドウ上なのかという判定は、
$XMODIFERSの設定有無で行っている。

実は、このやり方にはちょっと問題が出るケースが見つかった。

それは、Xウィンドウを立ち上げる前にtmuxを起動していた場合だ。
その場合、Xウィンドウ上でさらにtmuxを起動すると、tmux上のシェルでは$XMODIFERSが存在しなかった。

この挙動で困る人は$XAUTHORITYあたりをCUI/GUIの判定に使った方がいいかもめ。

2. Vimのモード遷移時の処理追加

次に、~/.vimrc(Neovimは~/.config/nvim/init.vim)に下記を追加しよう。

" IME control command
command! ImeOff silent !imectrl 0
command! ImeOn silent !imectrl 1

function! ImeAutoOff()
    let w:ime_status=system('imests')
    :silent ImeOff
endfunction

function! ImeAutoOn()
    if !exists('w:ime_status')
        let w:ime_status=0
    endif
    if w:ime_status==1
        :silent ImeOn
    endif
endfunction

" IME off when in insert mode
augroup InsertHook
    autocmd!
    autocmd InsertLeave * call ImeAutoOff()
    autocmd InsertEnter * call ImeAutoOn()
augroup END

imectrlについては、以前の記事を参照されたし。
もしくは、普段使っているIMEの制御コマンドに置き換えて頂きたい。

ちょっと解説

挿入モードを抜ける時、ImeAutoOff関数を呼び出す。
このとき、今回作成したスクリプト(imests)を呼び出してIMの状態を保存しておく。

挿入モードに入る時、ImeAutoOn関数を呼び出す。
このとき、保存していたIME状態がONだった場合は、IMEをONする。
関数内の最初のif文はちょっと手抜きだけど初回時の変数設定。

コードで怪しい箇所があればツッコミ下さいまし。

IME状態を管理する単位を調整したい場合

上のサンプルでは、Vimのウィンドウ単位でIMEの状態を保存している。
つまり、あるウィンドウのIME状態は、他のウィンドウには影響しない。

これをバッファごとに管理したい場合は、w:ime_statusb:ime_statusにすればいい。

もし、プロセスごとに管理したい場合は、w:ime_statusg:ime_statusにすればいい。

w:ime_statusは4箇所あるので、全部置き換えてねと。

最後に

今回の修正でVimでの日本語文章を書くのがちょっと気軽になった。

あと、C-oでのワンショットノーマルモードが使いやすくなった。

例えば、下のよう表形式のデータを入力している際、「ははは」まで入力したときに、
挿入モードのまま<C-o>jで次のitem2の行も続けて日本語を入力できる。
地味に嬉しい。

item1, ははは
item2, 
item3, 

今回紹介したやり方より良さげな方法があれば、ぜひ教えて下さいましまし。

参考

以上。