本記事では, T-Code-Engine ならびに T-Code IME for Android において, 部首合成の終端指定が必要になった理由について解説します. T-Code-Engine では終端指定はconvert() の呼び出しにて, T-Code IME for Android では SPC を押すことで指定することになります.

部首合成機能の考え方

部首合成の基本作用はまとめると, 以下のものがあります.

  1. (足し算)部品となる漢字の合成 (例: 木 + 目 = 相)

  2. (引き算)合成された漢字から特定の部品を取り除く (例: 頭 - 前 = 頁)

  3. (論理積)合成された漢字 2 つから共通部分を取り出す (例: 頭 ∧ 題 = 頁)

  4. (交換)類似形状の文字に入れ換える (例: 工(漢字) = エ(カナ) )

  5. (部分合成)合成された文字から部品を取り出し,他の部品と合成する (例: decomp(頭) + 工 = 項)

そしてこれら単体ないし帰納的に組合せて目当ての漢字を入力する機能が部首合成です. 問題となるのは, 4. 交換 が単一引数であることです.

後置と前置

部首合成機能は Prefix ▲(“jf”) を用いて呼び出します. TC のデフォルトは後置ですが, T-Code-Engine ならびに T-Code IME for Android では前置を採用しています. TC は Emacs 上で動作し, Emacs では編集中のバッファを elisp の関数を用いて操作することは一般的に行われるため, これは自然な実装といえます.

一方で, T-Code IME for Android では, アプリケーション(たとえば Chrome ブラウザのテキストエリア)上に入力することになりますが, アプリケーションに入力された文字列を IME が編集することには強い違和感があります. 実際, これを実装するためには, カーソル以前の文字を IME 側に読み込む必要があります. そして, Android ではこれが一般的に行われていることは事実ですが, そこにはセキュリティの観点で問題があると私は考えています. 実際,これを悪用することで,Android のファイルシステムの境界を無効化することが一般的に知られています. これを避けるため, 前置 Prefix とし, ユーザーの入力文字列をアプリ側にコミットする前に編集を確定させる方針をとりました.

前置式 Prefix の問題点もあります. それはつまり部首合成の終端が確定しないことです. たとえば▲エ と入力された時点では, 1-5 のうちどのルールを使用するのか確定しません. つまり本来ルール 1 の足し算としたい場合に, 勝手にルール 4 の交換を実施してしまっては, ユーザーの意図しない文字列が確定します. また, その逆も発生しえます. ▲頁▲ エ において, ルール 4 の交換後に合成したいケースでは, 次に入力があるのかわからないのです. これを避ける最も軽量な方法が,明示的に終端を与える, という方式なのです.

より高度な実装

前置 Prefix であっても明示的な終端の指定を求めない実装も考えられます. つまり, 内部で入力を構造化して保持しておき, 入力中にバッググラウンドで変換結果を計算して, 変換先の候補が単一になったときに自動で合成結果をアプリ側にコミットする方式です. 部首合成の入力は, ▲をノードとし, 葉は 1 文字または 2 文字の木構造としてモデル化することができます.

そして▲工 に続く文字が与えられた際に, 2 通りの木構造に分岐し, 各木構造を並列で評価し続け, 変換候補がなくなる時に当該の木構造を破棄するという実装が考えられます. この方式は一見するとより便利に見えますが, 実際にはユーザーの誤入力があることを想定すると, 実装がかなり煩雑なる一方で, 期待するほどの効果はないのかもしれません.

そのため, この方式を採用するには, 一定期間の実験が必要になるでしょう.