Emacsで文字に色を付ける
Emacsは文字に色を付けられる。こう言うと、どのテキストエディタにでもある当たり前の機能だと思うかもしれない。もちろんその通りなのだが、Emacsではそのような基本的な機能が露出しており、ユーザー自身が即座にそして一時的に一部分に色を付けられる。そのためエディタ自身を拡張しやすく、それが他のテキストエディタと異なる所であり、僕好みな所でもある。本稿では、そんな文字に色を付けるという基本的な機能について考えてみる。
色付けの基本
Emacsで文字列に対して色を付ける基本的な仕組みを確認していく。検証用のファイル testing.txt を作成しEmacsで開いておこう。また testing.txt のバッファが、なるべくプレーンな状態になるように M-x fundamental-mode で、 fundamental-mode に切り替えておこう。
M-x fundamental-mode RET
次に検証用の文字列を作成し、シンボル foo に束縛する。
(setq foo "Hello, world!")これらのバッファと文字列を使用し、挙動を確認する。
テキストプロパティ - 文字列に特性を設定する
Emacsでは文字列に対して特性を設定できる。これはテキストプロパティ(text property)と呼ばれる。 foo に束縛されている文字列に対して、 my-property というテキストプロパティを指定し、そこに1という値を設定してみる。
(add-text-properties 0 (length foo) '(my-property 1) foo)
ここで設定したテキストプロパティは、 add-text-properties によって取得できる。
(get-text-property 0 'my-property foo)1
このテキストプロパティは、Emacsの様々な機能の根幹の部分となっている。また、ここで設定された特性情報は、あくまでEmacsの管理する情報であり、バッファの内容をファイルに書き出したとしても、通常はファイルには保存されない。
フェイス - 文字列の外観に関する特性
文字列に face という名前のテキストプロパティが設定されている場合、その文字列がバッファに表示された時の外観情報として扱われる(これはフェースやフェイスと呼ばれるが、faceと表記される事が多い)。
face には plist(プロパティリスト、 (キー 値 キー 値 ...) と続くように作られたリスト)を設定する。指定するキーにも意味がある。例えば文字の色を変更したいなら、 :foreground をキーに指定し、値に色の設定を行う。例として文字の色を赤にしてみよう。
(add-text-properties 0 (length foo) '(face (:foreground "red")) foo)
この foo に束縛された文字列は、まだバッファ上に表示されていないため見た目は何も変わらない。しかしこれを insert を使ってバッファに書き出すと、確かに赤い「Hello world!」が表示される。
(insert foo) ;; この式を評価すると赤文字がバッファ上に表示されるEmacsではこの仕組みによって文字に色を付けている。Emacsで文字に色を付ける他の機能もこの仕組みの上に構築されている。
一部例外があるとすれば、docviewなど画像表示や、vtermなどの拡張されたターミナルエミュレータだろうか。それらは、この仕組みとは異なる技術が使われている。とはいえEmacsで文字に色付けといえば「faceテキストプロパティを設定する」と考えても概ね問題ない。
テキストプロパティ付き文字列を直接作る
先程は事前に文字列を作成しておき、その文字列に対してテキストプロパティを設定した。しかしテキストプロパティ付きの文字列を、直接作れた方が便利な事も多い。そのためにEmacsは propertize という関数をCで実装している。以下では赤い文字というテキストプロパティ付きの「注意」という文字列を作成している。
(propertize "注意" 'face '(:foreground "red"))これは以下のコードと概ね同じ結果となる。
(let ((txt "注意"))
(add-text-properties 0 (length txt) '(face (:foreground "red")) txt)
txt))実際に赤い文字で表示されるかは、バッファに書き込む事で確認できる。
(insert (propertize "注意" 'face '(:foreground "red")))hi-lockで色を付ける
hi-lock は、インタラクティブにハイライトを設定するためのマイナーモードを提供する。Emacsに同梱されているため、追加でパッケージをインストールする必要はない。
例えば hi-lock-face-phrase-buffer は、指定した文字列に対し、指定した色でハイライトを行う。
M-x hi-lock-face-phrase-buffer RET 文字列 RET 色を選択
一時的に特定の文字列を目立たせたい時などに役に立つような、インターフェースを提供している。
font-lockで色を付ける
font-lock はプログラミング言語などのコードハイライトに用いられる仕組みであり、構文規則に基づいてハイライトを行う。
font-lock-add-keywords を使うと、ハイライト処理を行うルールを追加できる。 TODO や FIXME といったコメントを強調表示したい場合、次のようなEmacs Lispを評価する。
(font-lock-add-keywords nil
'(("\\<\\(TODO\\|FIXME\\):" 1 font-lock-warning-face t)))
hi-lock との棲み分けとしては、 hi-lock があくまで一時的なものであり、ルールが事前にわからないものを即座にハイライトする事に主眼を置いているのに対し、 font-lock は構文規則や事前にわかっているルールを元にハイライトする事に主眼を置いている。
まとめ
Emacsの文字に色を付ける方法と仕組みについて見てきた。基本的な要素であるテキストプロパティやfaceを用いた文字の色や外観の変更の仕組みを確認した。またEmacsに同梱されているハイライティングに関連するパッケージであるhi-lockやfont-lockの使い方を確認した。これらの機能を使う事で、Emacsを自分好みに近付けていける。
オーバーレイを利用した色付けについても触れたかったが、余裕がなくて書けなかった。それはまたいつか書こうと思う。