読者です 読者をやめる 読者になる 読者になる

ぐるっとぐりっど

日曜プログラマがいろいろ試してみたことを、後の自分のためにまとめておく場所

Windows環境でEmacs+C/Migemoの設定に詰まったのでメモ

はじめに

これまでは、Windows環境でemacsを使うのに、Meadowを使っていたので、日本語をローマ字で検索できる便利なmigemoも設定済のが用意されていた。しかし、最近Emacs24のWindowsバイナリの乗り換えた際に、migemoを自分で設定して、見事にはまったので切り分け内容含めてメモ。(ところでもしかしてMeadowって消滅した? 少なくともサイトは参照できなくなってる。)

導入

  • C/Migemoをインストールする

http://www.kaoriya.net/software/cmigemo/
からWindows用バイナリがダウンロードできるので、任意のフォルダに展開して、PATHを通しておく。

  • migemo.elをインストールする

C/Migemoには、emacsからmigemoを利用するインタフェース部分は含まれていないので、emacsmigemo.elを導入しておく。MELPAにあるので、M-x package-list-packagesでmigemoを探してインストールするだけでさくっとできる。

  • .emacsに設定を追加する

.emacsmigemoの設定を追加する。migemoの辞書ファイルは、~/.emacs.dに配置したので、変数user-emacs-directoryを利用した(これが過ちの元凶であることに気付かず。。。)。

※これは間違った設定なので要注意

;; migemo
(require 'migemo)
(setq migemo-dictionary (concat user-emacs-directory "etc/migemo-dict/utf-8/migemo-dict"))
(setq migemo-command "cmigemo")
(setq migemo-options '("-q" "--emacs" "-i" "\a"))
(setq migemo-user-dictionary nil)
(setq migemo-regex-dictionary nil)
(setq migemo-coding-system 'utf-8-unix)
(load-library "migemo")
(migemo-init)

そして、意気揚々とemacsを再起動して、適当なファイルを開いて、C-sして検索すると、ローマ字で日本語の検索ができ、、、ない><

ぐぐってみても、他の人も同じように設定しているようで、原因がわからなかったので、ひとつずつ原因を切り分けた。

切り分ける

migemo.elが動いているか

C-sしてみると、ミニバッファには

* [MIGEMO] I-search: 

と表示されている、が、例えばこのミニバッファに「iro」と入力してみても「environment」にはひっかかるのに、肝心の「色」にひっかからない。なのでemacs側は問題はなくて、cmigemo側が入力に対して正しい出力を返してくれないのが原因であることがわかる。

C/Migemo単体では動作するか

cmigemoがおかしいことがわかったので、コマンドプロンプトを起動して、以下のコマンドを実行してみる。
特に重要なのは、「-d」で辞書ファイル(migemo-dict)を指定する、というところ。

C:\>cmigemo -d C:\.emacs.d\etc\migemo-dict\utf-8\migemo-dict -e
migemo_open("C:\.emacs.d\etc\migemo-dict\utf-8\migemo-dict")=00000000002B7750
clock()=0.155000
QUERY: migemo
PATTERN: \(・申s-*・ケ\s-*・杤s-*・貼|繝歃s-*繧イ\s-*繝「\|縺ソ\s-*縺箪s-*繧・|・構s-*・噂s-*・Ⅸs-*・・s-*・構s-*・十|m\s-*i\s-*g\s-*e\s-*m\s-*o\)
QUERY:

文字化けしてるけどcmigemoの動作としてはOK。文字化けしたところは、「migemo」をローマ字として解釈した検索候補(「みげも」や「ミゲモ」など)が表示されている。なぜ文字化けしてるかというと、コマンドプロンプト文字コードUTF-8じゃなくてShift-JISだから。今回はcmigemo.exeがきちんと動作して辞書がちゃんと読みこめることを確認することが目的だからUTF-8の辞書を読み込んでる(辞書ファイルが壊れてる可能性もあるので)。

例えば辞書が指定したパスに存在しない場合は以下のようにアルファベットしか表示されなくて、ローマ字としての検索候補が表示されないのでおかしいことがわかる。

C:\>cmigemo -d C:\.emacs.d\etc\migemo-dict\utf-8\migemo-dict -e
migemo_open("C:\.emacs.d\etc\migemo-dict\utf-8\migemo-dict")=0000000000487750
clock()=0.001000
QUERY: migemo
PATTERN: m\s-*i\s-*g\s-*e\s-*m\s-*o
QUERY:

もちろん、Shift-JISの辞書を読み込めば文字化けせずに結果を確認できる。

C:\>cmigemo -d C:\.emacs.d\etc\migemo-dict\cp932\migemo-dict -e
migemo_open("D:\MyDocuments\.emacs.d\etc\migemo-dict\cp932\migemo-dict")=0000000000287750
clock()=0.125000
QUERY: migemo
PATTERN: \(ミ\s-*ケ\s-*゙\s-*モ\|ミ\s-*ゲ\s-*モ\|み\s-*げ\s-*も\|m\s-*i\s-*g\s-*e\s-*m\s-*o\|m\s-*i\s-*g\s-*e\s-*m\s-*o\)
QUERY:

migemo.elからcmigemoの呼出がおかしくないか調べる

migemo.el単体もおかしくない、cmigemo単体もおかしくない。となればもはや怪しいのはmigemo.elとcmigemo.exeの連携部分がおかしいとしか思えない。
C-sではログがあまり出ず、調査が難しかったので、M-x migemo-forwardを実行してみた。
すると以下のログが出る。

migemo-forward: Search failed: "i\\s-*r\\s-*o"

ん?これだけ?

もっと色とか候補が出るはずなのに、アルファベットしか出ない。これは切り分け2の辞書ファイルの指定がおかしいときの結果と同じだ。
で、ここまで気付かなかったのだけど、migemoemacsの中で完結しておらず、emacsから、cmigemo.exeという別プロセスに検索するアルファベットを渡して、cmigemoがそれをローマ字として解釈した日本語を返すので、emacsでその日本語を検索する、という動作になる。つまり、cmigemoの起動オプションの辞書の指定がおかしい可能性が高いということだ。

cmigemo.exeの引数を確認する

cmigemo.exeの引数を確認したいのだけど、Windows 7のタスクマネージャでは、プロセスの引数を確認することができない。Process Explorer(https://technet.microsoft.com/ja-jp/sysinternals/bb896653.aspx)を使えば確認できるはずだけど、今回はコマンドプロンプトでできるやり方で確認してみた。

コマンドプロンプトで以下のコマンドを実行すると、cmigemo.exeに関するいろいろな情報を表示できる。

C:\>wmic  PROCESS where "Name='cmigemo.exe'" list FULL

CommandLine=(cmigemoのインストールPATH)\cmigemo.exe -q --emacs -i a -d ~/.emacs.d/etc/migemo-dict/utf-8/migemo-dict
(後略)

プロセスに関する情報が大量に出るけど、必要なのは一行目のCommandLineだけ。
そして、切り分け2の通り、「-d」オプションが辞書の指定だけど、、、「~/.emacs.d」って、これじゃWindowsがきちんとパスを解釈できないので、辞書をきちんと読み込むことができない。-dオプションには、「migemo-dictionary」にsetqした値が直接渡されるんだね。emacsなら~/.emacs.d/をC:\.emacs.d\として扱えるけど、
別プロセス(というかWindows)は、~を利用できないので、引数の渡し方には注意が必要ということでした。

正しい設定

user-emacs-directoryを評価すると「~/.emacs.d/」となってしまうので、「~/」を使わないように、
以下のようにmigemo-dictionaryをuser-emacs-directoryを使わずに書いたら、Windowsでもmigemoできるようになりました。

;; migemo
(require 'migemo)
(setq migemo-dictionary "C:/.emacs.d/etc/migemo-dict/utf-8/migemo-dict")
(setq migemo-command "cmigemo")
(setq migemo-options '("-q" "--emacs" "-i" "\a"))
(setq migemo-user-dictionary nil)
(setq migemo-regex-dictionary nil)
(setq migemo-coding-system 'utf-8-unix)
(load-library "migemo")
(migemo-init)

まとめ

emacsの中では、ホームディレクトリを「~/」で表現できるけど、あくまでもemacsの中だけなので、外部プロセスを利用する場合は要注意。特に変数を利用すると、ぱっと見では、どこが原因かわかりにくい。
※もしかして、cygwin導入環境ならうまく解釈してくれるかも? cygwin入れてないので未検証なので単なる予想だけど。