Vimperatorのコマンドラインで自動的にIMEをオフにする

VimperatorのコマンドラインIMEがオンになっていると, f等でヒントを選択できなくて困ることがある. 32ビットのWindows XPを使っていたときは, ime_controller.jsを使うことでコマンドラインや挿入モードでは自動的にIMEをオフにすることができたけれど, 他の環境でうまく動作しなくて困っていた.

ime_controller.jsが動かないのはFirefoxにおけるCSSのime-modeプロパティの動作環境が限られているのが原因で, Firefoxに限らずたとえばIME and DiMENSiONもうちの環境(Windows 7 64ビット)では動作が不完全(たまにIMEの状態が反映されない, IMEのオン・オフを制御できない)だったりして, IMEをアプリケーションから制御すること自体が難しいらしい*1.

そんな中で, Linux上のVimperatorからSCIMのオン・オフを制御する方法を見つけた:
Linux + Vimperator2.x で hint時にIMをオフにする - 備忘録 beta

これは, IMEのオンとオフのショートカットキーを個別に割り当てておいて, Vimperatorから外部コマンドを呼び出すことでキー入力をエミュレートするという手法. この方法ならWindowsにも対応できることに気づいたので, Vimperatorのプラグインを実装してみた.

追記 2011-05-24T23:16+0000

コマンドラインIMEオフにしたいだけならはてなグループの終了日を2020年1月31日(金)に決定しました - はてなの告知の方法でうまくいくことが多いようなので, こちらでうまくいく場合はこちらを推奨.

Windows 7 64ビットを使い始めたときに, ime_controller.jsがうまく動かなくなって, それでIME and DiMENSiON等の代替案をいろいろ試した覚えがあるのだけれど, 今試してみるとそもそもime_controller.jsでもうまくいく. 勘違い? それともFirefoxの特定のバージョンでime-modeがサポートされていなかったことがあった?

追記 2012-12-04T09:34+0000

ibusがインストールされている場合にはショートカットキーではなくpythonスクリプトでon/offするように変更. ibus(正確にはibus-setup)が入っているけれど使ってないという場合は

let g:imekeys_methods='x,w'

のようにする.

追記 2014-01-04T16:32+0000

uimがインストールされている場合はショートカットキーではなく共有ライブラリのAPI(uim-helper)経由でon/offするように変更. libuim.soが読み込めるか, /sbin/ldconfig -plibuim.so.VERSIONが見つかる環境で動作する.

最新のibusでは動かなくなってしまったので, ibusuimもインストールされている環境でuimのみを使うようにする場合は,

let g:imekeys_methods='uim'

のようにする. Windows環境や, uimがなかったときにはとりあえずホットキーによる動作にフォールバックする場合は

let g:imekeys_methods='uim,x,w'

のようにする.

動作確認環境

OS (IME)
Windows XP 32ビット, 7 64ビット (MS-IME, Google日本語入力) / Linux (ibus, SCIM)
ブラウザ
Firefox 4.0.1-17.0.1 (Vimperator 3.1-3.5)

やり方

  1. imekeys.js (これが今回作ったもの)をVimperatorのプラグインディレクトリに入れておく
  2. _libly.jsも入れておく
  3. 環境ごとの設定をする

環境ごとの設定

Linux (uim)
" コマンドラインで自動的にオフ(他にinsertおよびcmd,insertを指定可能)
let g:imeoff='cmd'
Linux (ibus)

ibusのon/offの概念が消滅して最新のibusでは動かなくなったので注意! (参考: iBusがクソになった理由 — KaoriYa)

" コマンドラインで自動的にオフ(他にinsertおよびcmd,insertを指定可能)
let g:imeoff='cmd'
Linux (SCIM)
  1. xvkbdをインストールしておく
  2. SCIMの設定を開いて, [フロントエンド]からオン・オフのホットキーを設定する(Shiftが含まれている方がよい(後述))
  3. .vimperatorrcに以下のように設定を書く(Windows設定と共存可能)
" Ctrl+Shift+$でオン
let g:ime_activate_xkey='\[Control]\[Shift]$'

" Ctrl+Shift+Spaceでオフ
let g:ime_deactivate_xkey='\[Control]\[Shift] '

" コマンドラインで自動的にオフ(他にinsertおよびcmd,insertを指定可能)
let g:imeoff='cmd'

キー設定の書式はman xvkbdの-textの項目を参照.

Windows
  1. Windows XPの場合は [テキストサービスと入力言語]の[詳細設定]タブで[詳細なテキストサービスのサポートをプログラムのすべてに拡張する]を有効にしておく
  2. IMEのオン・オフのキーを設定する(Shiftが含まれている方がよい(後述))
    • MS-IMEはプロパティのキー設定から
    • Google日本語入力はプロパティのキー設定を[カスタム]にして[編集](今まで使っていたキー設定を[定義済みのキーマップからインポート]しておくとよい)
  3. .vimperatorrcに以下のように設定を書く(Linux設定と共存可能)
" Ctrl+F11でオフ
let g:ime_activate_wkey='^{F11}'

" Ctrl+Shift+F11でオフ
let g:ime_deactivate_wkey='^+{F11}'

" コマンドラインで自動的にオフ(他にinsertおよびcmd,insertを指定可能)
let g:imeoff='cmd'

キー設定の書式はhttp://msdn.microsoft.com/ja-jp/library/cc364423.aspxを参照.

注意点
  • Fでヒントを表示するときなど, Shiftを離す前にキーイベントが送信されることもあるので, Shiftを押しっぱなしにしていても問題のないキーを割り当てておく方が安全
  • Windowsの場合, オン・オフのキーを個別に指定できればどんなIMEでも対応できる. ただし, IMEによっては動作しない場合もあり(うちの環境ではskkimeでオフのキーのみ設定してもトグルしてしまった).
  • Vimperator起動後は:set imeoff=string,listや:set imeon=string,listで自動的にIMEを制御するコンテキストを設定できる(設定できるオプションは補完候補を参照)

Vimperatorプラグイン開発者向け情報

  • liberator.plugins.sendKeys("xxx")でキーイベントがエミュレートされる
    • 文字列ではなくハッシュ{ x: "xxx", w: "yyy" }にして環境依存のキー文字列を渡すのも可
      • x: Linux用のキー文字列
      • w: Windows用のキー文字列
    • エミュレート方法は環境にあわせて自動選択される(利用できるものがなければ何もしない)
  • liberator.plugins.imekeys.on() / .off()でIMEを制御できる

しくみ

  • SCIMとxvkbdを使ったやり方を参考にして, Windowsではwscript.exeを使うだけ
    • WshShellオブジェクトのSendKeysメソッドを使う
    • wscript.exeには引数文字列をevalするオプションがないので, 初回実行時に一時ファイルにJScriptソースを書き出してファイル名を渡すようにする
  • Vimperatorのio.systemはシェルを挟んだりしてうざいのでio.runを使う

TODOなど

  • ドキュメント書く
  • verboseレベルに応じてエラーメッセージを出力
  • github.com:vimpr/vimperator-plugins.gitにコミット? (その前にリポジトリへの参加申請をする)
  • Mac対応は環境がないのでやりません(誰かやって下さい)
  • .vimperatorrcに書かなくても自動でキー設定とってこれたらいいな
  • SKKが使えないのがつらい......

*1:IME and DiMENSiONはFlash PlayerのIME制御機能を使っているので, FirefoxだけでなくFlash PlayerもIMEの扱いに難儀している模様