パスワードを忘れた? アカウント作成
289635 journal

dodaの日記: IME 制御 2

日記 by doda

Tera Term で接続している先(やそこから更に接続した先…)で起動した vim で、ローカルの Windows の IME を制御してみたくなった。
具体的にやりたい事は、挿入モードから抜けた時に IME が on ならば off にして、再度挿入モードに入った時に on に戻すという感じ。
ホスト側の vim からローカル側の IME を直接制御する事は当然出来ないので、IME の制御は Tera Term が行い、vim は制御シーケンスを使って Tera Term に依頼する形にするのが自然だろうか。

必要な機能としてまず挙げられるのは、IME の on/offf。
他に思いつくのは IME の現在の状態の問い合わせ。
この場合、vim 側で IME の状態を管理する事になる。
ただ、状態問い合わせには双方向でのやりとりが発生するので面倒だし、そもそも自分が vim について詳しくないのでちょっと荷が重そう。

二つ目の案として、IME の on/off の他に IME 状態の保存/復元機能を追加するというのがある。
動作としては、挿入モードから抜ける時に IME 状態の保存を行った後に IME を off にし、挿入モードに入った時に IME 状態を復元を行う。
これならば vim 側は挿入モードに出入りする時に決まった制御シーケンスを送るだけですむので、挿入モードでのカーソル形状変更と同じように t_SI/t_EI を設定するだけで済みそう。

難易度的には第二案の方が低そうなので、この線で行ってみる。

次にどのような制御シーケンスを使うか。
独自の制御シーケンスを使う事になるが、他の端末エミュレータを使う時の事を考えて出来るだけ悪影響を与えないような物がいい。
制御シーケンスとしては ESC, CSI, DCS, OSC, SOS, PM, APC などがある。
しかし、SOS, PM, APC は正しく無視できない端末エミュレータが結構ある。
また、OSC, や DSC も正しく無視できない端末エミュレータがそれなりにある。
ESC シーケンスは、独自(Private)な使い方が ECMA-48 では規定されていないし、他とのバッティングを避けるのが面倒そう。
という事で、CSI シーケンスを使うのが一番無難そう。

独自の CSI シーケンスを使う場合、Private な Final Byte (0x70-0x7e) か Private Parameter (0x3c-0x3f)、場合によっては Intermediate Byte (0x20-0x2f) を組み合わせて使う。
他とのバッティングを避けるには Intermediate Byte を 2 バイト以上使うといいのだが、Intermediate Byte を全く扱えないような腐った端末エミュレータも世の中にはあるので、出来れば Intermediate Byte を使うのは避けたい。
とりあえずは Private Parameter と Private な Final Byte を組み合わせて、Intermediate Byte は使わない方向で考えてみる。

Private Parameter では < を使うのがよさそう。他で使っているのを見た事が無いし、all-escapes.txt でも見当たらない。
Private な Final Byte はとりあえず r, s, t を使う事にしてみる。
とりあえず、CSI < r で IME 状態復元、CSI < s で CSI < 0 t で IME off、CSI < 1 t で IME on としてみる。
IME 状態保存/復元で Final Byte を分けたのは、0/1 と保存/復元の対応が連想しづらそうに思ったから。
r -> Restore、s -> Save ならば想像しやすそいかなと。
off/on が 0/1 なのは連想しやすいので、こちらは一緒にした。

という事で、実装してみた

使い方は、.vimrc に以下を追加する。

let &t_SI .= "\e[<r"
let &t_EI .= "\e[<s\e[<0t"
let &t_te .= "\e[<0t\e[<s"

t_SI は挿入モードに入った時に送出されるシーケンス。IME 状態の復元を行う。
t_EI は挿入モードから出た時に送出されるシーケンス。IME 状態の保存を行った後、IME を off にする。
t_te は vim が終了する時に送出されるシーケンス。IME の保存状態をクリアする為に、IME を off にした後にその状態を保存する。

で、実際に使った感想だけど…ちょっと微妙な出来。
挿入モードから抜ける為に ESC を押した後に t_EI で設定したシーケンスが送出されるまでに 1 秒程度あるため、その間のキー入力が IME に食われる。
一応、set timeoutlen=100 等として ESC 後の待ち時間を設定する事が出来るが、あまり短くすると他に問題が出そう。
もう一つ大きい問題として、screen/tmux が独自の制御シーケンスを食べてしまい、Tera Term に伝わらないというのがある。
こちらは対処方法が見つかっていない。

実装して見たが出来がちょっと微妙なので、採用するかどうかはちょっと保留しよう。
追加プラグイン扱いくらいがちょうどいいように思うが、その為にはできれば制御シーケンスの解釈をフック出来るようにしてそれを使う方がいい。
これに関しては別途検討しよう。
# 現在の TTX の枠組みの中でも力技で実装出来ない事は無いが、効率が悪いのと、誤動作対策が面倒

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • by ribbon (11750) on 2011年01月12日 20時33分 (#1886973) 日記

    ターミナルで日本語を使う場合、ホスト側のかな漢字変換がうまく使えないので、
    Windows側のかな漢字変換を使う事になるのですが、英数字を入力しなければ
    ならない場面で、かな漢字変換をOFFにする事を忘れて、操作に失敗することが
    よくあります。ホスト側のアプリケーションからかな漢字変換を制御できれば、
    単純ミスが減らせるのでとても便利だと思います。

    • by doda (31157) on 2011年01月14日 1時27分 (#1887694) 日記

      自分が試験的に実装してみたのも、まさにこれが理由です。
      日記とかも CygTerm 上の vim で書いているので。

      Application Escape モードのおかげで実用的に使えるようになったので、正式採用してもいいのかもしれませんね。

      親コメント
typodupeerror

クラックを法規制強化で止められると思ってる奴は頭がおかしい -- あるアレゲ人

読み込み中...