UP | HOME

Emacs のフォントを設定して Org-mode を美しくする

概要

[2022-02-26 Sat] 作成.

srd-emacs-font-setting.png
図 1: 設定後のスクリーンショット

ことフォントに関しては、Emacs の柔軟性に適うエディタはそう無いと思う。これを生かし、 text-mode 全般では sans-serif のプロポーショナルフォントを使い、 org-mode, markdown-mode などのヘディングやタイトルを serif のプロポーショナルフォントにしたい。

Symbol は自分で設定

まず設定が必要なのは、 (setq use-default-font-for-symbols nil) である1。 Symbol にデフォルトフォントを設定するというもの。これを nil にする。

正直今でも必要なのかは不明なのだが、入れておいて損はないと思う。

Emacs のフォント用語

Emacs 公式のマニュアル2に詳しく書いてあるのだが、ここではそこからかいつまんで紹介する。

font-family
フォントの名前。 (font-family-list) に使用可能なフォント一覧がある。
ここでは Unicode で考えるが、それぞれのフォントには対応する文字(グリフ)とそうでないものがある。例えば、アルファベットは表示できるが日本語は表示できないフォント、アルファベットと数式用のグリフにのみ対応するものなどだ。
fontconfig

Linux などでシステムのフォントを記述するときに使われている(いた?)形式3

Monospace-12:weight=bold:slant=italic

のように フォント名-サイズ:形式 1:形式 2:形式 3: … とする。フォント名以外は省略可。

XLFD

X Logical Font Description の略。歴史的な形式。

-maker-family-weight-slant-widthtype-style-pixels-height-horiz-vert-spacing-width-registry-encoding

のそれぞれを指定する。指定しない場合は * で埋める。例えば:

-*-sarasa ui j-regular-r-normal-*-*-*-*-*-p-*-fontset-sans_proportional

のようにする。詳しくはここ2の XLFD の部分を参照。

font-spec
Emacs 上でフォントを扱う上での基本単位といえる形式4
:family に font-family を設定できる他、 :name で Fontconfig や XLFD 形式で柔軟に指定できる。
Emacs でフォントを指定する際に頻出する形式であり重要。
fontset
Unicode のグリフの区画と font-spec を対応づけて、例えばアルファベットはフォント A、日本語はフォント B、などのまとまりを一つの fontset として名付けて設定できる。
describe-fontset で一覧が確認できる。
face
Emacs のあらゆる表示部分は、その種別ごとに face と呼ばれる5
例えばプログラムのコメント部分は font-lock-comment-face が対応する。
フォント、太字や斜体などのスタイル、文字色や背景色などなどを設定できるのだが、fontset を指定できるので非常に融通が利く。 describe-face で調べることができるほか、 list-faces-display で一覧表示できる。

実際の設定

text-mode つまり .txt, .md, .org など全般に対して、デフォルトの face を variable-pitch にする variable-pitch-mode を利用する。ここでは二つ目の variable-pitch が欲しいので、新たに variable-pitch-alt という名前の face を定義する。

  (defface variable-pitch-alt '((t :weight normal))
    "user defined face: used instead of variable-pitch(sans vs serif etc.)."
    :group 'basic-faces)

ここでは variable-pitch に serif(明朝系)のプロポーショナルな fontset を設定し、 variable-pitch-alt に sans-serif(ゴシック系)のプロポーショナルな fontset を設定する。ついでに fixed-pitch に等幅な fontset を設定する。

  ;; serif_proportional --------------------------------------------------
  ;; latin:vollkorn:weight=medium,
  (create-fontset-from-fontset-spec
   "-*-noto serif cjk jp-medium-r-normal-*-*-*-*-*-p-*-fontset-serif_proportional,
   latin:merriweather:width=regular,
   cyrillic:vollkorn:weight=medium")

  (set-face-attribute 'variable-pitch-alt nil :height 140
                      :font "fontset-serif_proportional"
                      :fontset "fontset-serif_proportional")

  (dolist (charset '(kana han cjk-misc hangul kanbun bopomofo))
    (set-fontset-font "fontset-serif_proportional" charset
                      (font-spec :family "Noto Serif CJK JP") nil 'append))
  (set-fontset-font "fontset-serif_proportional" '(#x2100 . #x214f)
                    (font-spec :family "DejaVu Math TeX Gyre") nil 'prepend)
  (set-fontset-font "fontset-serif_proportional" '(#x2200 . #x22ff)
                    (font-spec :family "DejaVu Math TeX Gyre") nil 'prepend)
  (set-fontset-font "fontset-serif_proportional" '(#x2900 . #x2aff)
                    (font-spec :family "DejaVu Math TeX Gyre") nil 'prepend)
  (set-fontset-font "fontset-serif_proportional" '(#x1d400 . #x1d7ff)
                    (font-spec :family "DejaVu Math TeX Gyre") nil 'prepend)
  (set-fontset-font "fontset-serif_proportional" 'unicode
                    (font-spec :family "DejaVu Serif") nil 'append)

非常に繁雑だが、部分ごとに確認する。また、自分が確認した限りでは、順番は非常に重要である。

まず create-fontset-from-fontset-spec で、fontset で核となるフォントを設定する。
XLFD 形式に fontconfig(文字区画ごと)を合わせた文字列を渡している。これで正しくセットできるのだから謎である。

次に set-face-attribute で face を設定する。ここで先に設定した fontset を渡す。
なぜか :font だけでも :fontset だけでも正確には動作しないのでどちらも必要。Emacs はさっぱり分からない。

最後に set-fontset-font で fontset に font-spec を追加する。
末尾にある 'append'prepend があるのだが、前者は基準となる fontset よりも優先度が低いのに対して、 後者は基準となる fontset よりも優先度が高い。優先して使いたいが基準のフォントを邪魔してほしくない 'prepend した font-spec は、グリフの範囲を絞っている('(#x2100 . #x214f) など)。逆に表示できなくて困らないように 'append した font-spec は、ほぼあらゆるグリフをカバーする範囲である 'unicode を指定した。

あとは同様に各 fontset を設定していけば良いが、フォントサイズに同じ指定をしても微妙にずれたりして不満な際は、以下のように拡大縮小する。

  ;; font-size ------------------------------------------------------------
  (setq face-font-rescale-alist
        '(
          (".*Noto Serif CJK.*" . 1.0)
          (".*Rubik.*" . 1.0)
          (".*Vollkorn.*" . 1.1)
          ;; (".*mononoki.*" . 0.92)
          (".*merriweeather.*" . 0.90)
          ;; (".*Hiragino Sans.*" . 1.0)
          (".*sarasa.*" . 1.0)
          (".*STIX.*" . 0.96)
          ("-cdac$" . 1.3)
          ))

最後に、ここまでで定めた variable-pitch, variable-pitch-alt, fixed-pitch を他の face に継承させる。この部分は基本的な Emacs, Spacemacs, Doom Emacs とで設定方法が異なるため、ここでは比較的情報の少ない Doom Emacs での書き方を紹介する。

(defun private/set-fonts (&optional _rest)
  ;; 上述の設定全部
  )

(add-hook! '(after-setting-font-hook after-make-frame-functions)
           :append 'private/set-fonts)

まわりくどいが、アドホックで上の設定を呼び出す6

(custom-set-faces!
  '(org-default :inherit variable-pitch)
  '(org-indent  :inherit (fixed-pitch org-hide))
  '(org-link    :underline t :inherit fixed-pitch)
  '((org-meta-line org-verbatim org-date org-todo
                   org-done org-footnote org-formula
                   org-block org-checkbox org-table
                   org-special-keyword org-ellipsis
                   org-document-info-keyword
                   org-block-begin-line org-drawer)
    :inherit fixed-pitch)
  '(org-block-end-line :inherit org-block-begin-line)
  '(outline-1 :height 1.4  :weight bold :inherit variable-pitch-alt)
  '(outline-2 :height 1.3  :weight bold :inherit variable-pitch-alt)
  '(outline-3 :height 1.2  :weight bold :inherit variable-pitch-alt)
  '(outline-4 :height 1.17 :weight bold :inherit variable-pitch-alt)
  '(outline-5 :height 1.13 :weight bold :inherit variable-pitch-alt)
  '(outline-6 :height 1.1  :weight bold :inherit variable-pitch-alt)
  '(outline-7 :height 1.1  :weight bold :inherit variable-pitch-alt)
  '(outline-8 :height 1.1  :weight bold :inherit variable-pitch-alt)
  '(org-document-title          :height 1.4 :weight bold :inherit variable-pitch-alt)
  '(org-superstar-header-bullet :height 1.2 :weight bold :inherit variable-pitch-alt)
  '(org-latex-and-related :inherit (variable-pitch-alt org-formula))
  '(org-sexp-date         :inherit (fixed-pitch org-latex-and-related))
  )

Emacs のフォント設定はほんとうに大変だが、達成感はすごいので、時間をつくって挑戦してみてほしい。

脚注:

Created: 2022-02-27 Sun 01:33