よもやもダンプ

気が向いた時にアウトプットしておくところ

EmacsでMMLのシンタックスハイライトをする

自分はMMLを書くのにEmacsを使ってます。
普段からテキストエディタとして使っていて、別のMMLエディタの操作を改めて覚えるのが面倒くさくてEmacsでやるようになりました。
ただ、MMLを読み込んでも、C言語などのソースファイルを読み込んだときみたいに文章の色分け(シンタックスハイライト)をしてくれません。色分けがないと単色の文字がずらずらっと並んでいてコマンドと音符の区別がつかず、目が疲れてしまいました。

調べてみるとシンタックスハイライトはメジャーモードというモード設定で指定しているみたいで、EmacsにはMMLモードがありませんでした(当たり前か…)。Emacs Lispの知識もほとんどありませんが、いろいろ調べながら「なら、作ってしまえ!」と勢いだけで作ってみることにしました。

とりあえず最近はPMDを触ることが多くなってきたのでPMD用MMLのメジャーモードを作ってみることにしました。

generic-modeを使う

Emacsにはgeneric-modeというのが用意されていて、これを使うことで簡単にシンタックスハイライトをしてくれます。
指定したいことを必要なところに埋めていけばいいだけなのでとても便利です。Emacs Lispを大して知らなくてもメジャーモードが作れました。

ブロックコメントの指定はコメントの始まりと終わりの文字列は違うものでないと判断できないようで、PMDのMMLではどちらもバッククウォートで表現するので実装を断念しました。

ハイライトする語は正規表現で指定します。
このとき、FONT-LOCK-LISTに登録した順で文字がハイライトされていくので、文字が重複しているときは判断の優先順位を考えないといけません。例えば"ABC"と"BC"の"BC"が重複している2つの語をそれぞれ別の色で表示したいときには、 “ABC"のほうを先に記述しないと上手くハイライトされません。
最初はよく使うコマンドだけ色分けできたらいいと思っていましたが、作ってるうちにやっぱりやるんだったら全部判別できるようにしたいと思い、定義を追加していくと正規表現の重複が頻繁に起こって大変でした…

フェイスを追加する

文字の色やフォントなどの属性はフェイス(face)と呼ばれるもので定義します。
Emacsにはすでにある程度のフェイスは定義済みでM-x list-face-displayで一覧を表示できます。
ただ、(個人的に)コマンドのイメージに合った定義済みフェイスがなかったりしたので、一部自分で定義することにしました。

フェイスの定義はdeffaceで行います。
GNU Emacs Lispリファレンスマニュアル: Defining Faces

例えば、太字じゃない赤色で表示する音量系のコマンド用フェイス"pmd-volume"は以下のように定義できます。

(defface pmd-volume
  '((t (:foreground "#ff0000")))
  "face of volume in MML for PMD")

ちなみに色の指定はRGB値によるもの以外に、M-x list-colors-displayで表示される名前でも指定できます。

あと、フェイスをgeneric-modeで使用するため、変数にバインドしておきます。

(defvar pmd-volume 'pmd-volume)

.emacsに登録

Emacsの設定は.emacsファイルで行います。
これまでやってきた設定は.emacsに記述すると反映されます。ただ、メジャーモードという一つの機能設定のかたまりなので、他のメジャーモードのように別のEmacs Lispファイルとしてまとめておくことにしました。

;; 自作Emacs Lispファイルがあるディレクトリへパスを通す
(setq load-path (cons "~/.emacs.d/elisp" load-path))

;; MMLのメジャーモード読み込み
(require 'pmd-mode)

これを.emacsに追加します。
requireされたのでpmd-mode.elには、

(provide 'pmd-mode)

を追加しておきます。
あとはpmd-mode.elをelispディレクトリに移動して完了です。


完成したものの、やっぱり正規表現の重複があったりしてたびたび修正しました。最近はあまり見つからないので大丈夫になったかな?
結局、PMD以外にもFMP7のものも作りました。

やっぱりシンタックスハイライトがあるだけでも作業のしやすさが全然違います。ちょっとだけどEmacs Lispの勉強にもなりました。
作ったかいがあったなぁ…