EmacsのX Windowフォントの設定方法(1)

  • 投稿日:
  • by
  • カテゴリ:

筆者は普段EmacsをX Windowで使わない。そもそもX Windowを使っていないからだ。使うのはFreeBSDやLinuxで動くEmacsだが、WindowsからTelnetやSSHでアクセスしているので、キャラクターベースである。マウスも使わ(え)ない。
昔はパソコンの性能に対してWindowsが重かったので、FreeBSD+X Windowを愛用していたが、その時はEmacsも重かったので、Emacsはktermやrxvtの中でしか使わなかった。
そのさらに昔、大学の研究室にはX Windowの端末があったので、X上のEmacsを使おうと思えば使えたのだが、Emacsを知ると同時にTelnetも知ってしまい、EmacsをXで使う利点よりも、コンピューターを遠隔操作することの魅力に取り憑かれてしまったので、やはりEmacsは文字ベースの端末で使っていた。
だから、X上のEmacsのカスタマイズというのはほとんどやったことがなかった。

時代は変わって、Windows上の仮想マシンでX Windowがスムーズに動くようになった。先月、訳あって、仮想マシンにFreeBSD 7.3をインストールした。XもEmacsもインストールした。ところで、筆者は昨年より再びEmacsを使い始め、今Emacsがマイブームなのである。そのため、XのEmacsのカスタマイズもやり始めている。大学の研究室でEmacsに出会ってからの1x年に渡る旧知の仲、しかも歳を重ねて英語もEmacs Lispもそれなりに読めるようになった今、もはや何もつまずくことはなかろうと高を括っていたら、フォントの設定にコテンパンにやられてしまった。何ゆえかくも複雑なのであろうか。

たかがフォントの設定に膨大な時間を費やしてしまったので、調べまくったことをここにメモしていくことにする。

●Emacs 22と23の違い
Xのフォントに関して、Emacsのバージョン22と23とでは大きな違いがある。バージョン23ではXftがサポートされ、アンチエイリアスされた滑らかなフォントが表示できるのである。また、フォント名として、あの長ったらしいXLFD名のみでなく、Xftの短い名前も使える。

・通常のビットマップフォントの例
(東雲ゴシック 16ドット)
-shinonome-gothic-medium-r-normal-*-16-150-75-75-c-160-jisx02081990-0
-shinonome-gothic-medium-r-normal-*-16-150-75-75-c-80-iso8859-1
(Ayuゴシック 20ドット)
-ayu-gothic-medium-r-normal-*-20-190-75-75-c-200-jisx02081990-0
ayu-gothic-medium-r-normal--20-190-75-75-c-100-iso8859-1

・アンチエイリアスされたTrueTypeフォントの例(M+2VM+IPAG circle 14pt)
M+2VM+IPAG circle
M+2VM+IPAG circle

しかしながら、その分ちょっと重い。

●Emacs23起動後のフォント変更方法
Shift+左クリックで開くポップアップメニューの"Change Buffer Font..."を選ぶと、フォント選択ダイアログが出てくる。
ダイアログの下半分のプレビューエリアには、Xのセレクションを使って、日本語をペーストすることもできる。(別プロセスのウィンドウの日本語文字列を左ボタンでドラッグして選択し、ここに中ボタンでペーストする等)

しかし、これで設定したフォントはバッファローカルであり、終了時に保存されないどころか、別のファイルを開くと引き継がれない。

●Emacs23のフォントの設定方法(X resourcesを使う場合)
Emacsのフォントの設定は.emacsの中にも書けるが、.emacsに書くには考慮することが色々あって結構難しい。それに対し、Xのリソースに登録する方法は、無難で手軽である。
例えば、~/.Xdefaultsに次のように記述する。

Emacs.font: M+2VM+IPAG circle
"M+2VM+IPAG circle"は、筆者のお気に入りのフォントの名前である。
M+2VM+IPAG circleにすると、ウィンドウサイズが横に広がりすぎるので、ウィンドウサイズも指定する。
Emacs.geometry: 40x32+30+0
ウィンドウサイズが40×32文字、表示位置が(30,0)という意味である。

フォントサイズを変更するには、フォントの高さをpt単位で指定する。
Emacs*attributeHeight: 140
設定する値は実際のpt数の10倍である。14ptなら140、10.5ptなら105とする。
"*"でごまかすのでなく、default faceのattributeHeightだけ指定すれば良いはずなのだが、書き方がわからなかった。("Emacs.default.attributeHeight: 140"では効かなかった)

万一、デフォルト起動でEmacsのXftが有効にならない場合は、

Emacs.FontBackend: xft
を含めておくと良いらしい。

余談だが、Xのリソース設定を~/.Xdefaultsに書いている場合は、アプリケーションの起動時に毎回自動的に読み込まれるので、ここに書いてEmacsを起動すると、設定したフォントで起動する。Xのセッション起動時に読み込まれる~/.Xresourcesに書いている場合は、追記した内容をすぐに反映させるには、次のコマンドを実行すると、Xのリソースに登録される。
xrdb -merge ~/.Xresources

●Emacs23のフォントの設定方法(.emacsに書く場合)
筆者の環境では、たまにEmacs23は重いと感じることがあるため、Emacs22をデフォルトにしている。そのため、XのリソースをEmacs23の設定にしたくない。そのような場合は、.emacsにてフォントを設定することもできる。

フレームのフォントの変更はset-frame-font、フレームのサイズの変更はset-frame-sizeでできる。また、ありがちな問題として、これらの設定はC-x 5 2で別のフレームを開いた時に引き継がれないということがあるので、こういうのはdefault-frame-alistに登録する必要がある。ついでにEmacsのバージョンもチェックするようにして、

(when (>= emacs-major-version 23)
(when window-system
(set-frame-font "M+2VM+IPAG circle") ;最初のフレームのフォント設定
(set-frame-size (selected-frame) 40 32) ;最初のフレームのサイズ
(setq default-frame-alist ;以後のフレームの設定
(append '(
(width . 40)
(height . 32)
(font . "M+2VM+IPAG circle")
) default-frame-alist))
))
でOKである。

筆者の環境では、ここでset-frame-fontをしなくても、この後の処理で最初のフレームのフォントがdefault-frame-alistに書いたフォントになることが確認できたので、set-frame-fontは外した。フレームのサイズについては、このように明示的にset-frame-sizeしないと変わらなかった。

フォントサイズの設定は、詳細を省くが

(set-face-attribute 'default nil :height 140)
のようにするとできる。これはフレームに対する設定ではなく、"default" faceに対する設定である。.emacsにこれを書いても、最初のフレームに関してはfaceの設定は済んだ後なので、最初のフレームについては、face設定の再読み込みが必要である。
(when (>= emacs-major-version 23)
(when window-system
;;(set-frame-font "M+2VM+IPAG circle") ;最初のフレームのフォント設定
(set-frame-size (selected-frame) 40 32) ;最初のフレームのサイズ
(setq default-frame-alist ;以後のフレームの設定
(append '(
(width . 40)
(height . 32)
(font . "M+2VM+IPAG circle")
) default-frame-alist))
(set-face-attribute 'default nil ;default faceの設定
:height 140 ;フォント高さ(/10pt)
)
(face-set-after-frame-default (selected-frame)) ;;最初のフレームのface再読み込み(NG)
))
…が、筆者の環境ではすぐにフォントサイズが戻ってしまった。Emacsの起動時には.emacsが実行された後も色々な処理が走るので、そのどこかで別の値に再設定されてしまうのだろう。その処理が特定できなかったので、今回はEmacs起動の最後の方で実行されるwindow-setup-hookに登録して乗り切ることにした。
(when (>= emacs-major-version 23)
(when window-system
;;(set-frame-font "M+2VM+IPAG circle") ;最初のフレームのフォント設定
(set-frame-size (selected-frame) 40 32) ;最初のフレームのサイズ
(setq default-frame-alist ;以後のフレームの設定
(append '(
(width . 40)
(height . 32)
(font . "M+2VM+IPAG circle")
) default-frame-alist))
(set-face-attribute 'default nil ;default faceの設定
:height 140 ;フォント高さ(/10pt)
)

;;最初のフレームのfaceの再読み込み(後処理)
(add-hook 'window-setup-hook
'(lambda ()
(face-set-after-frame-default (selected-frame)
))
))

●使用できるフォント名の一覧を得る方法
"M+2VM+IPAG circle"のような短い名前の一覧は、シェルでfc-listコマンドを実行すると出てくる。日本語名称はUTF-8で出てくるので、M-x shellで実行する場合は、C-x RET p(M-x set-buffer-process-coding-system)でUTF-8を指定しておくと良い。
Emacsで使えるフォントの一覧は、X上で起動したEmacsで、elispの

(x-list-fonts "*")
を実行すると得られる。但し、結果はXLFD名("-shinonome-gothic-medium-r-normal-*-16-150-75-75-c-160-jisx02081990-0"のような長い名前)のリストであり、例えば*scratch*バッファでC-jやC-x C-eでこれを実行すると、長過ぎて後ろの方が省略されてしまう。そういう時の定跡はprin1-to-string関数でオブジェクトを文字列に変換することであるが、しかし例えば
(insert (prin1-to-string (x-list-fonts "*")))
とすると、全てが改行されずに表示されてしまう。従って、例えば強引であるが
(mapcar (lambda(x) (insert x "¥n")) (x-list-fonts "*"))
のように実行するのがお勧めである。


やってみた感想として、Xのフォントの設定は、可能な限り.emacsでなくXのリソースで設定するのが良いと思う。

今回、FreeBSD 7.3のpackagesから手当たり次第にフォントをインストールして日本語フォントを見比べた結果、筆者は"M+2VM+IPAG circle"が最も気に入った。
また、そのフォントに含まれる欧文フォントであるBitstream Vera Sans Monoは、M+IPAフォントのサイト引用しているサイトによると、プログラマーに最も人気があるフォントだそうである。
他の参考リンク:
Free Japnese True Type Fonts for Linux

Emacsの起動時に何がどういう順序で行われるかは、Emacs LispのInfoの"System Interface"の所に詳しく書かれている。Emacs LispのInfoを表示するには、C-h rで開くEmacs Infoの最初のリンクを辿るのが早い。なぜEmacsのInfoでなくElispのInfoに書かれているのだろう。何度見てもInfoを開くと迷子になり、探し回る羽目になってしまった。

.emacsでフォントの高さをdefault faceに設定してface-set-after-frame-defaultしても最初のフレームのサイズがface-set-after-frame-defaultする前のサイズに戻ってしまうことについては、フォントスタイル自体も.emacsの後で変更されるので、最初のフレームに対するフォント設定をどこかでやっているのだろうが、その時はdefault faceは見ず、しかしdefault-frame-alistのフォントスタイルは見ているということになる。不可解である。その処理がどのelispにあるのか、またElisp Infoが示す実行順序のどの段階で行われるのかは、調べ切れなかった。