Emacs で LilyPond を使う

 LilyPond には emacs のモード設定ファイルが含まれている。Mac 版では、LilyPond.app/Contents/Resources/share/emacs/site-lisp に置いてある。Cocoa emacs (emacs 23 ベース) で使ってみた。

 Emacs 側の設定だが、初期設定は ~/.emacs.d ディレクトリ内に置かれているものとする。~/.emacs.d/init.el に以下の内容を書き込んでおく。

;; Add .emacs.d/lisp to load-path (let ((default-directory (expand-file-name "~/.emacs.d/lisp"))) (add-to-list 'load-path default-directory) (if (fboundp 'normal-top-level-add-subdirs-to-load-path) (normal-top-level-add-subdirs-to-load-path))) ;; Lilypond mode (autoload 'LilyPond-mode "lilypond-mode") (setq auto-mode-alist (cons '("\\.ly$" . LilyPond-mode) auto-mode-alist)) (add-hook 'LilyPond-mode-hook 'turn-on-font-lock)

 そして、~/.emacs.d/lisp 以下のどこか(サブディレクトリの中でもいい)に LilyPond モードのファイルを置けばよい。今回は ~/.emacs.d/lisp/lilypond ディレクトリ内に入れることにした。

 いくつか問題を発見した。一つは、シンタックスカラーリングがブロックコメント(%{...%})に対して正しく働かない場合があること。手元の組み合わせ(LilyPond 2.12.2/Emacs 23.1)では、次のブロックコメントが正しくカラーリングされない。

%{ 01234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789 01234567890123456789012345678901234567890123456789 %}

 "01234..." の行を1つ削ると正しくカラーリングされる。lilypond-mode.el からたどってみると、lilypond-font-lock.el の108行目に次のような記述があり、これがブロックコメントにマッチすることになっている。

;; "on top", ... (multiline-)comments '("\\(%\\({[^%]*%\\(}\\|\\([^}][^%]*%\\)+}\\)\\|.*\\)\\)" 0 font-lock-comment-face t)

 しかし、emacs のマニュアルを見ると、複数行にわたるカラーリングはちょっと面倒で、*-font-lock-keywords で改行を越えてマッチするパターンを書いても動作しないことになっている(Multiline Font Lock - GNU Emacs Lisp Reference Manual)。だから、上の記述(LilyPond-font-lock-keywords の中にある)が動いたり動かなかったりするのは仕様。修正する方法はあるみたいだけど、まだうまくいってないので、とりあえずはブロックコメントはごく短いもの以外は使わないことにする。

 もう1つは、ときどき閉じカッコをタイプしたあと勝手にナローイングモードになってしまうこと。これは、過去に lilypond-user メーリングリストで質問している人がいるのだが、何が起きているのか誰も理解しないまま放置されているみたい。実際、これはかなり複雑なスコアでしか再現しないみたいで、僕もどういう条件で発生するのか完全には特定できていない。どこでナローイングが起きているのか調べてみたところ、LilyPond-blink-matching-parenの中に narrow-to-region の呼び出しがあったので、その前後を save-restriction で囲んでみた。一応修正できたみたい。

--- lilypond-indent.orig.el 2011-11-13 00:32:00.000000000 +0900 +++ lilypond-indent.el 2011-11-13 13:24:43.000000000 +0900 @@ -499,6 +499,7 @@ (setq char-before-bracket-type (if char-before-bracket-type nil ?\\))) (if (eq char-before-bracket-type ?\\) (setq bracket-type (string char-before-bracket-type bracket-type))))) + (save-restriction (when blink-matching-paren-distance (narrow-to-region (max (point-min) (- (point) blink-matching-paren-distance)) @@ -510,7 +511,7 @@ ;; whereas ( ) slurs within music don't, so only need to search for ( ) ;; use same mechanism for [ ] slurs (LilyPond-scan-containing-sexp bracket-type t dir)) - (setq blinkpos (point)) + (setq blinkpos (point))) (setq mismatch (or (null (LilyPond-matching-paren (char-after blinkpos))) (/= (char-after oldpos)

 また、imenu を有効にしておくと、Bassoon = { ... などで始まる行がメニューから選択でき、直接その行に飛ぶことができる。下記を init.el に追記すればよい。

;; Add Imenu menu to the menu bar (add-hook 'LilyPond-mode-hook (lambda () (imenu-add-to-menubar "Imenu")))

(2011/11/13 作成)