2017/09/05

Recent entries from same category

  1. VimConf 2023 Tiny に参加しました
  2. Vim で Go 言語を書くために行った引越し作業 2020年度版
  3. Vim をモダンな IDE に変える LSP の設定
  4. ぼくがかんがえたさいきょうの Vim のこうせい 2019年 年末版
  5. VimConf 2019 を終えて

8/31、patch 8.0.1026 で Linux 版 Vim のとある挙動が修正されました。

patch 8.0.1026: GTK on-the-spot input has problems - vim/vim@5c6dbcb - GitHub
https://github.com/vim/vim/commit/5c6dbcb03fa552d7b0e61c8fcf425147eb6bf7d5
この修正は、Linux 版 Vim の IME (Input Method Editor) の挙動を修正する物ですが、この1つのパッチの為に多くの開発者が動いたという話です。

Vim と IME と僕

このパッチ、多い時で月に100個以上もリリースされる大量のパッチの1つに過ぎないのですが、実はこのパッチには思い入れがあり記事にせずにいられませんでした。この問題が修正されるまでに至った経緯を知っている人間には、色々な思い出が脳裏を掛けめぐるのです。

これまでの UNIX 版 Vim の IME の挙動は、正直言って使い物になるとは言えませんでした。

これは vim-dev が悪い訳でも、我々マルチバイト圏の開発者が悪い訳でもなく、Vim というモードのあるテキストエディタに IME を連携させようと戦ってきた中で、如何にしても実現出来ない問題があった、という事なのです。

UNIX の IME

僕が vim-dev にパッチを送り始めたのは、おそらく Vim に IME の実装が入ったちょっと後だったと思います。Windows に至っては香り屋さんの多大な貢献もあり既に動作は安定し始めていました。その頃の UNIX の IME の実装は、Athena や Motif、GTK1 の GUI 上に XIM の実装が行われていました。今では当然の様にある GTK IM Module がまだ無かった頃ですね。とは言っても X11 XIM (X11R6) はその頃には既に実装も枯れていて、必要と思われる機能は十分に揃っていました。

入力エージェントの選択肢と言えば kinput2 くらいしか無く、有償であれば ATOK、その他で無償で使えた物と言えば VJE Delta くらいだったかもしれません。ここは記憶違いもあるかもしれません。特殊な入力方法を X11 上に提供する skkinput が世に出回ったのもその頃だったかもしれません。エンジンの方は Wnn、Canna、Sj3 などありました。そうは言ってもエージェントとエンジンが明確に区別されている訳ではなく、kinput2 に Wnn のパッチを当てた kinput2-wnn、kinput2 に canna のパッチを当てた kinput2-canna、といった具合にそれぞれに向けたパッチがあったという UNIX らしい提供方式でした。

今から思えば UNIX の日本語入力はお世辞にも使いやすいとは言えませんでした。今の様に当然の様に日本語入力できる訳でなく、自分でインストールして設定しなければならないのです。端末から日本語を入力するには skkfep の様に常駐して FEP を提供する物を使うか、kterm (この言葉知ってるともうオッサンと呼んでいい) から kinput2 を使う方式が一般的でした。CUI 単独で IME を使う方法は皆無で、あの頃みんなどうやって日本語を入力してたんだろうと今思えば不思議なくらいでした。

そんな頃 2ch で skk.vim という Vim script だけで SKK スタイルの入力を行うプラグインが話題に上がり、Vim 界隈で一世を風靡しました。これは後に tyru さんが skk.vim を作り直して eskk.vim をリリースする事になります。

しかし SKK は癖があります。また skk.vim の様なプラグインで実現する入力機構は他の Vim プラグインと干渉してエラーになったり画面が崩れる事も多く、それを自力で回避できるユーザでないと使いこなせないのが実状でした。その頃だったでしょうか、nvi-m17n という nvi のマルチリンガル対応版が canna と直接喋る事が出来ていて、Vim 使いとしては少し悔しい思いをしたのを覚えています。どうしても CUI で日本語入力したかった僕は、vim から Wnn や canna、POBox、SKK が使える様にするパッチ im_custom という物を作って配り始めました。しかしパッチという提供方法は Vim 本体の変更に追従しなければいけません。いつしか追従する気力を失った僕は、im_custom を最新版の Vim に追従するのを辞めてしまいました。

ON/OFF 問題

その頃の Vim の日本語入力も進展が無かったという訳ではなく、我々マルチバイト圏の開発者が試行錯誤を繰り返していました。その頃の Vim の日本語入力で一番辛かったのが IME の ON/OFF 問題でした。Vim は ESC でインサートモードから抜けますが、その際に IME が ON だった場合は一旦 IME をオフにしてから ESC (CTRL-[) を押す必要がありました。そうしないとノーマルモードで IME が ON の状態になったままとなり、jjj とタイプしても IME に食われて反応しないのです。Windows の IME に関しては ImmSetOpenStatus という Win32 API を使って IME の ON/OFF が実装され、シームレスなモードの行き来が行える様になっていました。しかし XIM には IME を ON/OFF させる仕組みがありません。その頃の Vim 使いは文句を言いながら IME の ON/OFF を繰り返していたに違いありません。

ところで Vim の IME がデフォルトでアクティブになる問題をご存じでしょうか。これは僕が vim-dev に参加するよりも前から実装されていた動作でした。Windows の GVim で以下を実行し、インサートモードに移るといきなり IME がアクティブになっているのです。

gvim --clean -u NONE -U NONE -N

この挙動は iminsert というオプションを使ってある程度制御が可能です。ただ、このオプションのデフォルト値が IME が使える場合には 2、つまり IM がオンという動作です。インサートモードに入ると IME が ON になるのです。デフォルト値が 2 になった経緯は我々日本人ではなく、最初に XIM の実装を始めた韓国の開発者による物でした。これは彼らの入力方法と日本人の入力方法が異なる事に起因しています。その頃に調べた所によると彼らの使う IME はアクティブになった後もローマ字が打てるらしいのです。なので iminsert が 2 であっても良いという事でした。丁度 skkinput が大文字でタイプを始めないと IME がアクティブ状態にならないのと同じと思って貰えると分かりやすいと思います。色々と葛藤はありましたが、結局のところ日本のユーザは vimrc で iminsert を 0 に設定して貰う事になっています。

我々日本人と他の IME ユーザの入力方法の違いはそれだけではありません。例えば日本人の IME 操作は、単語もしくは文節までを一度平仮名で仮入力を行い、その一部または全体を漢字に変換しながら確定して行きます。しかし中国や韓国の IME は文字単位です。特に韓国の IME ではアルファベット文字を幾らかタイプして1文字を入力し、都度確定していくらしいのです。つまりプリエディット(仮入力)が1文字という事です。

さて、話を IME の ON/OFF に戻します。これらの問題に香り屋さん取り組み、そして X11 のキーボードイベントをルートウィンドウに投げる事で IME を強制オフにするというワークアラウンド実装「imactivatekey」を思い付き、パッチとして取り込まれました。これはワークアラウンドながら実に良く動作しました。Linux デスクトップの IME 問題が一気に解決した様に見えました。

しかしそんな穏やかな日々を壊す物が現れます。GTK2 でした。GTK2 は IM Module を介して日本語入力を行います。そして GTK IM Module には IME を ON/OFF する機能が無いのです。今まで iminsert や imactivatekey というオプションで IME の ON/OFF が制御出来ていていたにも関わらず、もはやどうしようも無くなってしまったのです。uim に特化するのであれば vim から uim-fep を制御するパッチなんていうのもありました。

CustomizeUim - uim/uim-doc-ja Wiki - GitHub
https://github.com/uim/uim-doc-ja/wiki/CustomizeUim#vim%E3%81%A7%E4%BD%BF%E3%81%86

我々日本人開発者も、この頃はもう打つ手がないというのが正直な所でした。

仮入力問題

Vim の日本語入力にはもう一つ大きな問題がありました。それは仮入力の問題です。UNIX の IME には4つの入力方式がありました。

  • オーバーザスポット
  • オンザスポット
  • オフザスポット
  • ルートウィンドウ

それぞれの入力方式については以下のドキュメントに分かりやすく書かれています。

Seamonkey インプットメソッド仕様書

Seamonkey インプットメソッド仕様書 著者: Tague Griffith このドキュメントの内容: インプットメソッドの編集方式 プラットフォームのプロトコル エディターの関数 参考文献 イ...

https://www.mozilla-japan.org/projects/intl/input-method-spec.html

Windows の IME で一般的に使われるのはこのうちオンザスポットとオーバーザスポットです。メモ帳の様にキャレット上に仮入力がオーバーレイされているのがオーバーザスポット、MS Word の様に後続する文字も一緒に動きながら仮入力を行うのがオンザスポットです。Vim の実装上、本来であればオーバーザスポットが相応しいはずです。Windows 版の Vim もオーバーザスポットです。しかしながら GTK2 版においてはなぜか初回の実装からオンスポットになっており、しかもオンザスポットでしか入力出来ない様になっていました。

そしてまぁこのオンザスポット版にはたくさんバグがありました。そりゃそうです。IME からのコールバックで文字を自ら描画しないといけないのですから、IME と Vim で整合性を取らないといけません。しかも Vim 側の実装方式も良く無かった。Vim の基本実装は、文字入力と画面表示が明確に分けて実装されています。この文字入力部分に IME から貰った仮入力文字を流し込み、例えば「かんじ」という入力から「漢字」という仮入力に変換する際、「"かんじ" の3文字を消しながら "漢字" を挿入」といった実装になっていたのです。この方式を実装するにはいろいろな所に手を入れないといけません。もし仮入力をキャンセルするのであれば、現在の仮入力を全て「カーソル左」と「デリートキー」で削除しないといけないのです。しかもこの入力が map の影響を受けてしまっており、例えばカーソルキーに別のキーを割り当てていると IME の仮入力が目も当てられない状況になるです。

僕は問題が見付かる度にパッチを送りました。バグが見つかる度に ifdef XIM のコードが増えて行き、次第に Vim の開発者 Bram 氏も二つ返事でパッチを取り込んでくれなくなってしまいました。これがバージョン7の頃だったと思います。我々 vim-jp も何時しか vim-dev に XIM 関連のパッチを送る事が無くなってしまいました。

日本人にとって、Vim にとって、きちんと日本語入力を行う為には、もはやオーバーザスポットしかあり得なかったのです。 中平さんが作ってくれたオーバーザスポットのパッチは我々の一つの望みでもあったのですが、Bram 氏は取り込んでくれませんでした。

この時点で、Linux の GVim で問題なく日本語を入力する術が無くなってしまったのです。

そんな半ばあきらめムードだったのですが、一筋の光明が現れます。

terminal、お前だったのか

Vim に terminal が実装され出し、Vim のコミット量が一気に増えました。

vim-dev

そしてふと、こんな事を思いついたのです。

今のオンザスポット入力方式だと、後続のテキストが動いてしまうので今の terminal の実装では画面が壊れちゃうよなー

そんな思いで中平さんのパッチについて GitHub Issues で突いてみたのです。

Mapping backspace while typing Korean - Issue #1215 - vim/vim - GitHub
https://github.com/vim/vim/issues/1215

まぁ何時もの様に Bram 氏から返事は返ってこないだろうなと思っていた所、思いもよらぬリプライが。

Bram「それは中平が書いたパッチを k-takata が改良した奴の事かい?」

これは心が躍りました。急いで「そうだよ!」と返事を返しました。半信半疑でどきどきしながら待ちました。

そして先日の朝、patch 8.0.1026 として、1つのパッチが取り込まれました。早朝このコミットに気付いた僕は早く最新の Vim をコンパイルしたくて溜まらないくらいに心が躍ったのを覚えています。

数ある中の1コミットかもしれませんが、多くの日本人開発者が悩んで実装して壊されて、それでも戦ってきた歴史が、僕の脳裏には蘇ってきたのです。

そして時代も良い方向に動き始めました。現在の Linux デスクトップで日本語入力と言えば fcitx が一般的です。そして fcitx はコマンドから IME を ON/OFF 出来るのです。

Vimからfcitxを使う - Qiita

近頃の ibus や uim の使い勝手がイマイチなこともあり、Linux 上での Input Method として fcitx が最近ポピュラーになってきました。 我らが SKK では、その他のIn...

http://qiita.com/sgur/items/aa443bc2aed6fe0eb138

この記事の中に書かれている設定を行えば、ESC で日本語をオフに出来る様になります。

気付いたら、僕らを長年苦しめ続けて来た Linux 版 Vim の 日本語入力問題は、解決し始めていたのです。もちろん Bram 氏が動いてくれたのは、あの GitHub Issue が理由でもなく、terminal が直接の理由でもない事は覚えて覚えておかなければなりません。過去に繰り返しパッチを送り続けてくれた日本人 Vim 開発者の功績あってこそ、きちんとした日本語が入力出来る今の Vim がある事を。


追記 2017/09/16

提案したところ、なんと iminsert/imseach の値が 0 になりました!

patch 8.0.1114: default for 'iminsert' is annoying - vim/vim@4cf56bb - GitHub
https://github.com/vim/vim/commit/4cf56bbc85f77846aeb378cfb071677336dfad6d
Posted at by | Edit