generic.elで俺々モードを作る

Emacs Advent Calendar jp: 2010 : ATND 19日目です。昨日は [twitter:@r_takaishi] さんの org-modeとAnythingが交差するとき,物語は始まる - うどん駆動開発 でした。

Web漁ったり会社で Emacs 使ってる人に聞いたりしてると、みんな generic.el の事を知らないらしいので、ちょっと紹介してみようかと思います。

generic.el はハイライト程度の簡単なメジャーモードをお手軽に作るためのライブラリです。Emacs20くらいの昔から標準添付です。「このファイル用のモードってEmacsに無いなぁ」なんて時に使ったりします。

たとえば

例えばこんなシンタックスのファイルがあるとします

  • "#" ではじまるのはコメント
  • "/*", "*/" でかこまれてるのはコメント
  • hoge, fuga, piyo はキーワード
  • 数字には色を付けたい

そんなときはこんなのを.emacsとかに書いとけばいいんです。

(define-generic-mode hoge-fuga-piyo-mode
  ;; コメントになる文字列の指定
  '("#"
    ("/*" . "*/"))
  ;; キーワードの指定
  '("hoge" "fuga" "piyo")
  ;; もうちょっと難しいキーワードの指定
  '(("[0-9]+" . font-lock-constant-face))
  nil nil
  "Major mode for hoge, fuga, piyo")

そうするとこんな感じでハイライトしてくれます。便利。

ここで作った hoge-fuga-piyo-mode はちゃんとしたメジャーモードなので auto-mode-alist に設定することもできるし、hoge-fuga-piyo-mode-hook もちゃんと存在します。

define-generic-mode について

サンプルで大体分かるとは思いますが、define-generic-mode マクロの簡単な説明をしときます。

define-generic-mode はこんな風に宣言されてます。

(define-generic-mode MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST AUTO-MODE-LIST FUNCTION-LIST &optional DOCSTRING)
  • MODE: モード名。説明不要ですね。
  • COMMENT-LIST: コメントにしたい文字のリストを指定します。指定できるのは「文字」「2文字までの文字列」「コンスセル」。一行コメントの場合は文字にして、ブロックコメントを作りたい場合はコンスセルを使います。
  • KEYWORD-LIST: ハイライトするキーワードです。
  • FONT-LOCK-LIST: 直接 font-lock-keywords を書く場所。KEYWORD-LISTじゃ足りない場合にはこっちを使います。普通は "(REGEXP . FACE)" の羅列で済むと思います。
  • AUTO-MODE-LIST: ここに正規表現を書いておくと勝手に auto-mode-alist に登録してくれます。
  • FUNCTION-LIST: hook の実行前にここにある関数を実行してくれます。
  • DOCSTRING: docstringです。書いときましょう。

詳細は define-generic-mode の docstring を見てください。

auto-complete と組み合わせる

せっかくキーワードを指定してるんだから auto-complete と組み合わせないともったいないです。こんなのを定義しておけば、define-generic-mode で作ったモードで、キーワードの auto-complete ができるようになります。

(defvar ac-generic-keywords nil "Generic keywords for auto complete")
(defadvice generic-mode-internal
  (after
   generic-mode-with-ac
   (mode comment-list keyword-list font-lock-list function-list)
   activate)
  "Add generic keywords into `ac-generic-keywords'."
  (set (make-local-variable 'ac-generic-keywords)
       keyword-list)
  (setq ac-sources (cons 'ac-source-generic ac-sources)))
(defun ac-generic-candidates ()
  ac-generic-keywords)
(ac-define-source generic
  '((candidates . ac-generic-candidates)
    (symbol . "d")))

おしまい

こんな感じで generic.el の紹介はおしまいです。generic.el は Emacs 初心者さんでも新しいハイライトを作れるし個人的には結構気に入ってる機能の一つです。キーワードファイルから作れたりするともっといいかもしれないですね。

さて、明日は [twitter:@khiker] さんです。おたのしみに。