Hatena::ブログ(Diary)

日々、とんは語る。

この日記のはてなブックマーク数 はてなスターカウンター Peace この日記をあなたのはてなアンテナに追加する。 rss
お問い合わせ先 mailto

2009-12-18 超寒波の初日。

Mac の Emacs でツールチップ辞書を実現しよう。

| 21:08 |

id:peccu さんからバトンを受けとりました。2日目は インターバルタイマーインプット - ぺっくブログミラーでした。

Emacs Advent Calendar 2009 の3日目というわけで、相撲大好き Emacser の tomoya です。どすこんばんわ。

早速ですが、Mac では、OSX 10.5 から、ネイティブアプリケーションで、Control + Commnad + d を押しながらクリックすると、辞書ツールチップが表示されて超便利です。

f:id:tomoya:20091218212116j:image

前から Emacs で実現したかったこの機能ですが、ようやく実現できるようになったので紹介します。

コマンドラインから辞書をひけるようにする。

Emacs から Dictionary.app を開くのは、dict:// なスキームを使うと可能なのですが、それだと Dictionary.app にフォーカスが移ってしまうため、サクサク使うには億劫です。

コマンドラインから辞書が扱えるようになれば、Emacs で結果を受けとることができるのですが、tekezo さんが コマンドラインから Dictionary.appという記事で公開しているコードを使うと、コマンドラインから高速に辞書をひくことが可能になります。

お好きなディレクトリで、

$ hg clone http://hg.pqrs.org/commandline-dictionary-app

として、ソースを取得するか、http://hg.pqrs.org/commandline-dictionary-app/index.cgi/archive/tip.tar.gz からファイルダウンロードしましょう。

僕は、/Users/tomoya/projects ディレクトリ以下に色々なソースコードリポジトリを貯めているので、もれなく ~/projects/commandline-dictionary-app にクローンしています。

src ディレクトリに移動して、make すると、dict コマンドが生成されます。

表示の関係から、僕は dict.m の 47行目付近の区切り線を消してから make しました。

popup.elツールチップを実現。

id:m2ym さんが auto-complete.el から独立させた popup.el を使います (参考 popup.elによるポップアップメニュー、カスケードポップアップメニュー、ツールチップの実現

git clone git://github.com/m2ym/auto-complete.git

で全体を取得するか、http://github.com/m2ym/auto-complete/raw/master/popup.el からダウンロードできます。

僕は、~/projects/auto-complete に取得しています。

で、Emacs から呼び出すための関数を作ります。

辞書引き関数を書き換えました。Mac の Emacs でツールチップ辞書 パート2。を参考にしてください。

(defun ns-popup-dictionary ()
   "カーソル付近の単語を Mac の辞書でひく"
   (interactive)
   (let ((word (substring-no-properties (thing-at-point 'word)))
	 (old-buf (current-buffer))
	 (dict-buf (get-buffer-create "*dictionary.app*"))
	 (view-mode-p)
	 (dict))
     (set-buffer dict-buf)
     (erase-buffer)
     (call-process "/Users/tomoya/projects/commandline-dictionary-app/src/dict"
		   nil "*dictionary.app*" t word
		   "Japanese-English" "Japanese" "Japanese Synonyms")
     (setq dict (buffer-string))
     (set-buffer old-buf)
     (when view-mode
       (view-mode)
       (setq view-mode-p t))
     (popup-tip dict)
     (when view-mode-p
       (view-mode))))

(define-key global-map (kbd "C-M-d") 'ns-popup-dictionary)

とりあえず動作するように、先程でっちあげた代物なのでまだまだ問題がありますが、Control + Meta + d のキーバインドで、カーソル位置の単語辞書でひかれて、ツールチップ出来るようになりました。

関数の簡単な解説。
  1. 内部変数として「カーソル付近のワードを取得したもの : word」「現在の利用中のバッファ : old-buf」「辞書読み込み用のバッファ : dict-buf」「view-mode であるかどうか : view-mode-p」「辞書の内容の文字列 : dict」を格納するものを用意しました。
  2. set-buffer 関数は表示を切り替えずに、バッファフォーカスを変更する関数です。*dictionary.app* バッファフォーカスを変更します。
  3. erase-buffer 関数フォーカスされているバッファの内容を消去する関数です。*dictionary.app* バッファ初期化します。
  4. call-process は同期的に、外部プロセスを呼び出します。*dictionary.app* バッファコマンドラインで引いた辞書の内容を読み込んでいます。参考:Emacs内でのプロセス制御について - 武蔵の日記
  5. dict 変数に *dictionary.app* バッファ文字列を代入します。
  6. (set-buffer old-buf) で、元のバッファフォーカスを戻します。
  7. when view-mode... は、もし、view-mode であれば、view-mode を解除して、view-mode であったことを記録します。view-mode だと、popup.el によるツールチップが表示できないので、一時的にオフにします。
  8. (popup-tip dict) で辞書の内容をツールチップ表示します。
  9. when view-mode-p... は、view-mode だった場合、view-mode に戻します。

という内容の関数を ns-popup-dictionary と定義しました。

キーバインドの割り当ては、僕は Command を Super にしているので、本当は Control + Super + d にしたいのですが、なんかこのキーバンドに上手く割り当てが出来なくて、とりあえず C-M-d にしています。

f:id:tomoya:20091218225958j:image

辞書の表示はこんな感じです。幅とか調整すれば、もう少し綺麗になるはずです。

動画公開(はてなフォトライフのちっちゃいw 後で、YouTube に上げなおそうかしら。でも、雰囲気は十分伝わるかな?)

まとめ。

コードが非常にダサいです。もう少し、関数を整理しておきたいところです。

辞書サクサク利用しているムービーを公開する予定。録画が終ってるので、あとは、編集だけ。した。

というわけで、もう十分遅くなってしまったので、0時を回ってしまうまえに、公開しておきたいと思います。

明日は、iws さんです。よろしくお願いします。でも、ブログアドレスを知らない><。。

追記

4日目はiwsさんの 名前を付けた: Emacsと別アプリとの切り貼り連携をホームポジションでです。

<< 2009/12 >>
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Connection: close