Emacs のフォントを設定して Org-mode を美しくする
概要
作成.
ことフォントに関しては、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 のフォント設定はほんとうに大変だが、達成感はすごいので、時間をつくって挑戦してみてほしい。