Emacsのフォントを設定する

本記事は[Emacs Advent Calendar 2018](https://qiita.com/advent-calendar/2018/emacs)10日目、12/10公開･･･のはずが、12/12公開となってしまいました。遅くなってしまって申し訳ありませんm(__)m)

Emacsで鬼門とされることが多いフォントの設定。私も20年近くEmacsを使ってきてなんとなく他人の設定を真似したりしてやり過ごしてきましたが、一念発起してやり方を学んでみました。

Emacsのマニュアル（[21.8 Fonts - The Emacs Editor](https://www.gnu.org/software/emacs/manual/html_node/emacs/Fonts.html)、[同 日本語版](https://ayatakesi.github.io/emacs/26.1/html/Fonts.html)）を見ると、メニューからフォントを設定する方法や、X WindowsやGNOMEデスクトップなどで設定する方法も記載されています。しかしここでは、Mac OS X、Linux、WIndowsなどさまざまな環境に対応できるようEmacs Lispを使った設定方法をとりあげます。

## 前提知識

次の点について知識があれば、Emacsでのフォントの設定を理解しやすくなります。

- フォントとフォントファミリー
- XLFD

### フォントとフォントファミリー
フォント（font）というと一般に、「Times」や「Inconsolata」「ヒラギノ」「游ゴシック」などの字体を指すことが多いでしょう。しかし、Timesなどの字体は厳密にはフォントファミリー（font family）であり、フォントの一要素です。フォントはフォントファミリーのほか、太さ（weight）や、通常体かイタリック体か、サイズなどさまざまな要素を指定します。

### XLFD

XLFD（X Logical Font Description）は、もともとはUNIX上のX Window Systemで用いられ、Emacsでも採用されている次のようなフォントの表記方法です。

```
-*-Inconsolata-bold-italic-normal-*-*-*-*-*-m-0-iso10646-1
```


XLFDでは、フォントの次の要素を`-`で区切って並べたものです。要素の指定を省略する場合は、ワイルドカード`*`を指定します。

|要素 |説明 |
|:----------|:------------------------------|
|maker |フォントの製造者名。MacOSXやWindowsでは常に省略？|
|family |フォントファミリー|
|weight |フォントウエイト。`bold`（ボールド）、`medium`、`light`など|
|slant |`normal`（通常体）、`italic`（イタリック）、`oblique`（斜体）など|
|widthtype |フォントの幅。通常は、`normal`、`condensed`、`semicondensed`、`extended`のいずれか|
|style |追加のスタイル。通常は省略|
|pixels |フォントの高さをピクセル単位で指定。heightを指定した場合は省略|
|height |フォントの高さをプリンターのポイントの1/10の単位で指定。pixelsを指定した場合は省略|
|horiz |水平解像度（horizontal resolution）。通常は省略|
|vert |垂直解像度(vertical resolution)。通常は省略|
|spacing |文字の間隔。`m`（monospace）、`p`（proportional）、`c`（character cell）のいずれか|
|width |Emacsでは通常0？|
|registryとencoding |Emacsでは通常、`iso8859-1`|

そのため上記のXLFD`-*-Inconsolata-bold-italic-normal-*-*-*-*-*-m-0-iso10646-1`は、フォントファミリーInconsolataで、ボールドイタリック体、標準の幅のフォントを表します。

XLFDの詳細な仕様は、Emacsのマニュアルを参照してください。

XLFDは、とても人間が扱うような代物ではないとか、悪名高いようです。とはいえ、参照用としてはコンパクトで許容できる表記方法だと思います。自分でXLFDを記述するのはさすがに厭ですが。

## Emacsでのフォントの設定

### 使用可能なフォントファミリーの確認

Emacsで使用可能なフォントファミリーは、`font-family-list`関数で確認できます。Mac OS X上での`*scratch*`バッファーでの実行例を次に示します。

```:*scratch*バッファーで実行
(font-family-list)
("Al Bayan" "Al Nile" "Al Tarikh" "American Typewriter" "Andale Mono" "Arial" "Arial Black" "Arial Hebrew" "Arial Hebrew Scholar" "Arial Narrow" "Arial Rounded MT Bold" "Arial Unicode MS" "Athelas" "Avenir" "Avenir Next" "Avenir Next Condensed" "Ayuthaya" "Baghdad" "Bangla MN" "Bangla Sangam MN" "Baskerville" "Beirut" "Big Caslon" "BlairMdITC TT" "Bodoni 72" "Bodoni 72 Oldstyle" "Bodoni 72 Smallcaps" "Bodoni Ornaments" "Bordeaux Roman Bold LET" "Bradley Hand" "Brush Script MT" "Casual" "Chalkboard" "Chalkboard SE" "Chalkduster" "Charter" "Cochin" "Comic Sans MS" "Copperplate" "Corsiva Hebrew" "Courier" "Courier New" "Cracked" "Damascus" "DecoType Naskh" "Devanagari MT" "Devanagari Sangam MN" "Didot" "DIN Alternate" "DIN Condensed" "Diwan Kufi" "Diwan Thuluth" "Euphemia UCAS" "Farah" "Farisi" "Futura" "GB18030 Bitmap" "Geeza Pro" "Geneva" "Georgia" "Gill Sans" "Gujarati MT" "Gujarati Sangam MN" "Gurmukhi MN" "Gurmukhi MT" "Gurmukhi Sangam MN" "Handwriting - Dakota" "Heiti SC" "Heiti TC" "Helvetica" "Helvetica Neue" "Herculanum" "Hiragino Kaku Gothic Pro" "Hiragino Kaku Gothic ProN" "Hiragino Kaku Gothic Std" "Hiragino Kaku Gothic StdN" "Hiragino Maru Gothic Pro" "Hiragino Maru Gothic ProN" "Hiragino Mincho Pro" "Hiragino Mincho ProN" "Hiragino Sans" "Hiragino Sans GB" "Hoefler Text" "Impact" "InaiMathi" "Inconsolata" "Iowan Old Style" "ITF Devanagari" "ITF Devanagari Marathi" "Kailasa" "Kannada MN" "Kannada Sangam MN" "Kefa" "Khmer MN" "Khmer Sangam MN" "Kohinoor Bangla" "Kohinoor Devanagari" "Kohinoor Telugu" "Kokonor" "Krungthep" "KufiStandardGK" "Lao MN" "Lao Sangam MN" "Lucida Grande" "Luminari" "Malayalam MN" "Malayalam Sangam MN" "Marion" "Marker Felt" "Menlo" "Microsoft Sans Serif" "Mishafi" "Mishafi Gold" "Monaco" "Mshtakan" "Muna" "Myanmar MN" "Myanmar Sangam MN" "Nadeem" "New Peninim MT" "Noteworthy" "Noto Nastaliq Urdu" "Noto Sans Syriac Eastern" "Optima" "Oriya MN" "Oriya Sangam MN" "Palatino" "Papyrus" "Phosphate" "PingFang HK" "PingFang SC" "PingFang TC" "Plantagenet Cherokee" "PortagoITC TT" "PT Mono" "PT Sans" "PT Sans Caption" "PT Sans Narrow" "PT Serif" "PT Serif Caption" "Raanana" "Rockwell" "Sana" "Sathu" "Savoye LET" "Seravek" "Shree Devanagari 714" "SignPainter" "Silom" "Sinhala MN" "Sinhala Sangam MN" "Skia" "Snell Roundhand" "Songti SC" "Songti TC" "Source Han Code JP" "STIXGeneral" "STIXIntegralsD" "STIXIntegralsSm" "STIXIntegralsUp" "STIXIntegralsUpD" "STIXIntegralsUpSm" "STIXNonUnicode" "STIXSizeFiveSym" "STIXSizeFourSym" "STIXSizeOneSym" "STIXSizeThreeSym" "STIXSizeTwoSym" "STIXVariants" "STSong" "Sukhumvit Set" "Superclarendon" "Symbol" "Tahoma" "Tamil MN" "Tamil Sangam MN" "Telugu MN" "Telugu Sangam MN" "Thonburi" "Times" "Times New Roman" "Trattatello" "Trebuchet MS" "Verdana" "Waseem" "Webdings" "Wingdings" "Wingdings 2" "Wingdings 3" "Zapf Dingbats" "Zapfino" "Apple Braille" "Apple Chancery" "Apple Color Emoji" "Apple SD Gothic Neo" "Apple Symbols" "AppleGothic" "AppleMyungjo")
```

### 使用可能なフォントの確認

Emacsで使用可能なフォントのXLFDは、`x-list-fonts`関数に引数として使用可能なフォントファミリーを指定することで確認できます。次では、InconsolataというフォントファミリーのフォントをXLFDで表示しています。

```:*scratch*バッファーで実行
(x-list-fonts "Inconsolata")
("-*-Inconsolata-normal-normal-normal-*-*-*-*-*-m-0-iso10646-1" "-*-Inconsolata-normal-italic-normal-*-*-*-*-*-m-0-iso10646-1" "-*-Inconsolata-bold-normal-normal-*-*-*-*-*-m-0-iso10646-1" "-*-Inconsolata-bold-italic-normal-*-*-*-*-*-m-0-iso10646-1")
```

XLFDのweightとslantを見ると、通常（normal）ウエイトで通常体、通常ウエイトでイタリック体、ボールドウエイトで通常体、ボールドウエイトでイタリック体、という4種類のフォントが使用可能だとわかります。

### フォントの設定

Emacsでは、フォントは主に次の場所で設定されます。

- フレーム
- フェイス（face）

`default-frame-alist`での設定は、Emacsのすべてのフレームおよびバッファに影響します。一方、フェイスにフォントを設定することで、特定の文字列に対してフォントを設定することもできます。つまり、1文字ごとに異なるフォントを設定することもできます。

### フレームへのフォントの設定

フレームへフォントを設定する主な方法は、次のとおりです。

- 変数`default-frame-alist`など
- 関数`set-frame-font`

変数`default-frame-alist`では、たとえばフレームの幅や高さ、表示位置といったほかのフレームの属性といっしょに、フォントをXLFDで設定できます。`font-family-list`や`x-list-fonts`などの関数でフォント名を出力してコピペすれば、XLFDによるフォントの設定もラクにできるでしょう。`default-frame-alist`の設定例を以下に示します。

```
(setq default-frame-alist
    '(
      (width . 120)
      (height . 40)
      (top . 0)
      (left . 0)
      (font . "-*-Inconsolata-normal-normal-normal-*-*-*-*-*-m-0-iso10646-1")))
```

こうした記述は、Emacsの初期化ファイル`init.el`にするケースも多いと思います。

フレームにフォントだけを設定したい場合は、関数`set-frame-font`を用いることができます。

```
(set-frame-font "-*-Inconsolata-bold-italic-normal-*-*-*-*-*-m-0-iso10646-1")
```

## カーソル位置のフォントの確認

カーソル位置のフォントの設定は、次のコマンドで確認できます。

```
(font-xlfd-name (font-at (point)))
```

`font-at`は、指定された位置のフォントオブジェクトを返す関数です。`point`はカーソル位置を表す数値、`font-xlfd-name`はフォントオブジェクトのXLFDを返す関数です。

`default-frame-alist`変数や`set-frame-font`関数でフォントを設定してからアルファベットや（半角）数字にカーソルを合わせてから、`M-:`（eval-expression）で上記のコマンドを実行すれば、設定が正しく反映されているかどうかを確認できます。

次のような関数を定義しておけば、`M-x xlfd-cursor-position`でこうした作業がラクにできます。

```
(defun xlfd-at (pos)
  "Return X logical font description (XLFD) of the font at POS in the current buffer."
  (if (not (display-graphic-p))
      (message "Display is not graphic. So font is not used.")
    (font-xlfd-name (font-at pos))))

(defun xlfd-cursor-position (pos)
  "Return X logical font description (XLFD) of the font at the point."
  (interactive "d")
  (message (xlfd-at pos)))
```


## フォントとフォントセット

さて、ここまで述べてきたようなInconsolataフォントを設定した場合でも、漢字やかななどの部分には設定が反映されません。Inconsolataフォントは、アルファベットや数字などといったASCIIコードの範囲が対象となり、その範囲外の文字は別途フォントセット（FONTSET）の設定が必要です。

このあたり、海外の文字さえ使わなければ少ない設定で問題なく文字が表示できる英語圏の人がうらやましくなります。一方で、いい加減な設定でも日本語をちゃんと表示し、多少苦労すればきちんとした設定もできるEmacsはありがたいともいえるわけですが。

フォントセットについては、[Emacs のフォント設定を克服する - Out of Dimension](http://extra-vision.blogspot.com/2016/07/emacs.html)が参考になります。

このあたり、できれば別の記事でまとめたいと思っています。

## まとめ

Emacsのフォント設定にあたっては、フォントとフォントファミリーの違いとXLFD表記が前提の知識となります。フォントはフレームに`default-frame-alist`変数や`set-frame-font`関数で設定することができ、確認は`font-at`などでできます。