im_control.vim - IBus

IBus 1.5以降

IBus 1.5以降では開発方針の変更により、IME制御方法が変更されました。

IBusからはエンジンの切替のみを行い、状態制御等は行わないということのようです。

この場合、端末から"ibus"コマンドでエンジンの切替が行えるなら、im_control.vimが使えるということになります。

使えるエンジンはlist-engineコマンドで確認可能です。

$ ibus list-engine

エンジンはコマンドで切替可能です。

$ ibus engine "mozc-jp"

list-engineで認識されているエンジンを指定してください

直接入力へもコマンドで切替可能です。

$ ibus engine "xkb:jp::jpn"
$ ibus engine "xkb:us::eng"

コマンドで切替可能な事が確認出来た場合は、以下の設定を.vimrcに追加することでim_control.vimを使用することができます。

エンジン名は使用環境に合わせて変更してください。

" 「日本語入力固定モード」の動作モード

let IM_CtrlMode = 1

" 「日本語入力固定モード」切替キー

inoremap <silent> <C-j> <C-r>=IMState('FixMode')<CR>

" IBus 1.5以降

function! IMCtrl(cmd)

let cmd = a:cmd

if cmd == 'On'

let res = system('ibus engine "mozc-jp"')

elseif cmd == 'Off'

let res = system('ibus engine "xkb:jp::jpn"')

endif

return ''

endfunction

" <ESC>押下後のIM切替開始までの反応が遅い場合はttimeoutlenを短く設定してみてください。

" IMCtrl()のsystem()コマンド実行時に&を付けて非同期で実行するという方法でも体感速度が上がる場合があります。

set timeout timeoutlen=3000 ttimeoutlen=100

(pongoさん、ありがとうございます)

ただし同じIBus 1.5でも1.5.1と1.5.2では挙動が違うなど、開発方針は試行錯誤中のようです。

環境に応じて制御スクリプトは適宜変更してください。

IBus(1.4以前) + Python

IBus の1.4までを使用していてPythonが使える場合は Pythonスクリプトで IBusを制御可能です。

Vim自体の Pythonインターフェイスが無効でも、OSに Pythonがインストールされていれば以下の設定を.vimrcに追加することで動作します。

(動作確認 IBus 1.3.9, Ubuntu 10.10)

" 「日本語入力固定モード」切替キー

inoremap <silent> <C-j> <C-r>=IMState('FixMode')<CR>

" PythonによるIBus制御指定

let IM_CtrlIBusPython = 1

" <ESC>押下後のIM切替開始までの反応が遅い場合はttimeoutlenを短く設定してみてください。

set timeout timeoutlen=3000 ttimeoutlen=100

(注意) IM_CtrlModeを 1(デフォルト), 5以外に設定していると正常動作しません。必要なら明示的に指定してください。

その他の詳細設定については「IBus + Pythonのオプション」を参照してください。

以上の設定で「日本語入力固定モード」が使用可能になります。

日本語入力固定モードの使い方

この設定で正常動作を確認していますが、後述するIBusのvi協調モードのバグ対策のためデフォルトでは GVimでも「日本語入力固定モード」のvi協調モードを有効にしています。

IBusのvi協調モードが正常動作動作するようになった場合には不要な動作ですので以降を読んでおくと良いかもしれません。

IBusのvi協調モード(GVim)のバグについて

IBusにはGVimがノーマルモードへ移行したらIMをオフにするvi協調モードがあるのですが、IMをオンにしてから文字入力を行わないでノーマルモードへ戻るとIMがオフにならないというバグがあります。

たとえば IMの On/Offが <C-space>だとして i<C-space>hogefuga<CR><ESC> のように文字入力してから <ESC>だとノーマルモード移行時にIMがオフになりますが、 i<C-space><ESC> だとノーマルモード移行時に IMがオフになりません。

(このバグがあるかどうかは「日本語入力固定モード」を無効化して確認してみてください)

" 「日本語入力固定モード」を無効化

let IM_CtrlMode = 0

このバグは IBus 1.3.7-1.3.9 で確認しています。

このため本来は不要なのですが該当バグ対策のために「日本語入力固定モード」のvi協調モードも有効にしています。

ただし該当バグの挙動が気にならなければ、現時点でも下記設定を利用して「日本語入力固定モード」のvi協調モードを無効化したほうが操作感は良くなります。

" GVimの時だけ「日本語入力固定モード」のvi協調モードを無効化

let IM_vi_CooperativeMode = has('gui_running') ? 0 : 1

将来IBusのバグが修正された場合は上記設定を利用して「日本語入力固定モード」のvi協調モードを無効化してください。

使用している Pythonスクリプトが動作しない場合

IBusを制御するためのPythonスクリプトで current_input_contxt()を使用していますが、ドキュメントからするといわゆる typoなのではないかと思います。

Pythonがインストールされているのに動作しない、あるいはバージョンアップで動作しなくなった場合は以下が参考になるかもしれません。

http://d.hatena.ne.jp/fuenor/20110705

(わかる方は im_control.vimの該当部分を置換すると動作する可能性があります)

デフォルトでは~/.ibusに自動生成されたPythonスクリプトが使用されますのでそちらを書き換えてみてください。

" 自動生成するファイルの保存場所

let IM_CtrlIBusPythonFileDir = '~/.ibus'

IBus + Pythonのオプション

IBusを Pythonで制御する場合の制御方法を指定する事ができます。

IBusを Pythonで制御する場合は Pythonスクリプトが自動生成されることがあります。

保存場所は IM_CtrlIBusPythonFileDirで指定可能です。

" 自動生成するファイルの保存場所

let IM_CtrlIBusPythonFileDir = '~/.ibus'

将来的にPython3インターフェイスを使用して制御する必要がある場合はインターフェイス名に python3 を指定してください。

" 使用するPythonインターフェイスのバージョン

let IM_CtrlIBusPythonVer = 'python'

同期呼び出しと非同期呼び出し」で解説しているように IM制御は同期呼び出しで処理した方がよいのですが、IBusの vi協調モードとバッティングするのでデフォルトでは非同期呼び出しを行っています。

動作については呼び出し方法で挙動が異なることがあるので設定を変更してみてください。

" 制御スクリプトを同期処理で呼び出し

let IM_CtrlAsync = ''

" 制御スクリプトを非同期で呼び出し

let IM_CtrlAsync = '&'

今時の高速なマシンでは問題にならないようですが、気になる場合は IBusの vi協調モードを set iminsert=1 で無効化してから同期呼び出しに変更する方法があります。(IBus自体に vi協調モードを無効化するオプションが追加された場合はそちらを使用して下さい)

iminsertは vi協調モードを切るためのオプションではなく、結果的にそうなるというだけなので iminsertの動作について理解してから使用した方がよいでしょう。

なお set iminsert=1 を設定した場合 CursorIMで IMの状態を表示することが出来なくなります。

  • GVimで IM制御の同期呼び出しを行う (Pythonインターフェイスが使える場合)
      • " 「日本語入力固定モード」切替キー
      • inoremap <silent> <C-j> <C-r>=IMState('FixMode')<CR>
      • " Pythonインターフェイス制御のみ使用する
      • let IM_CtrlIBusPython = 2
      • if has('gui_running')
      • " iminsert=1を設定して IBusの vi協調モードを無効化する
      • set iminsert=1
      • endif
  • GVimで IM制御の同期呼び出しを行う (Pythonインターフェイスが使えない場合)
      • " 「日本語入力固定モード」切替キー
      • inoremap <silent> <C-j> <C-r>=IMState('FixMode')<CR>
      • " IBusをPythonで制御
      • let IM_CtrlIBusPython = 1
      • if has('gui_running')
      • " iminsert=1を設定して IBusの vi協調モードを無効化する
      • set iminsert=1
      • " 制御スクリプトを同期処理で呼び出し
      • let IM_CtrlAsync = ''
      • endif