Emacs (Viper/Vimpulse)で日本語の文節を扱う
というか、Emacsだとうまく文節ごとに削除してくれたりするんだろうか。それだったらすごいな。
http://twitter.com/tyru/status/19890157313
という話があったので, どうなっているか調べてみた. まず移動に関して, Emacsの単語移動コマンドforward-word/backward-word (M-f/M-b)は, 日本語の場合は文節(のようなもの)に働くらしく, 動作を見る限りは, 漢字の連続+ひらがなの連続をひとまとまりと見なしている感じ. 完全な文節ではないけれど, カーソル移動の単位として用いるには問題ないレベル. 実際にどういう処理をしているのか調べようと思ったけれど, forward-wordはEmacs LispではなくCで書かれているようで, ソースコードを読むのは面倒なので諦めた.
Emacs上に実装されたViエミュレータであるViperや, VimエミュレータであるVimpulseで, wやbがforward-word/backward-wordによって実現されていれば, diwで日本語の文節(のようなもの)をうまく削除してくれそうな気がする. ところが実際には, 単語の後ろに記号が続く場合の扱いがVi系とEmacsで異なるようで, forward-word/backward-wordを使わずに独自実装されているようだった. 実際の処理としては, viper-looking-at-alphaやviper-skip-alpha-forward/viper-skip-alpha-backwardで, 現在のカーソル位置がアルファベットかどうか, アルファベットが書かれていたらスキップする, という処理をしていた.
Viper/Vimpulseでは, 日本語の文字が非アルファベットかつ非記号の扱いになるのが原因で, 日本語が混ざった文章でw/bするとよくわからない単位でカーソルが移動するし, viwで単語選択しようとするとおかしな範囲が選択される. そこで, viper-looking-at-alphaを日本語も含めるように変更して, viper-skip-alpha-forward/viper-skip-alpha-backwardの内部でEmacsのforward-word/backward-wordを使うようにしてみた. これで, 日本語に関しては漢字の連続+ひらがなの連続のひとまとまりが単語として扱われる.
以下のファイルをload-pathのディレクトリに入れて,
http://github.com/tarao/vimpulse-plugins/raw/master/vimpulse-cjk.el
.emacs等に
(setq vimpulse-cjk-want-japanese-phrase-as-word t) (require 'vimpulse-cjk)
としておけばOK.
何も考えずにvimpulse-pluginsリポジトリに入れてしまったけれど, よく考えたらViperのコードしか関係していないからVimpulseではなくViperのプラグインなのだった. まぁいいか. 今後Vimpulse固有のCJKパッチを書く予定, ということにしておこう.
追記 2010-08-03T10:12:28+0000
- デフォルト動作をVim互換(コメント欄参照)に変更
- http://github.com/tarao/vimpulse-plugins/commit/70fd74cfc50a1cc60aaed7e45a250c2f4d053c37
- ただし-iw/-awではちょっと挙動が違う(Vimpulseの実装の問題もありそう)
- Emacsの文節の扱いを有効にする場合はvimpulse-cjk-want-japanese-phrase-as-wordをtにしておく(上述の設定)