emacsの日本語フォント
emacsの日本語フォントの設定難しいですね。いろいろな設定項目があるうえに、複雑な設定は必要な人が限られている(マルチバイト圏のみ)ので、全貌を知っている人も少ないです。設定の概要を簡単に解説しながら、フレーム全体のフォントをサイズ調節する方法を紹介します。環境はmacOSのemacs 25.1です。
設定の概要
- どの文字にどのフォントを割り振るかの一覧表
fontset
を定義する
これは、"a"、"あ"、"α"、など一文字一文字に使用するフォントを設定することを意味します。つまり、極端な例では"あ"、"い"、"う"、"え"、"お"、にすべて違うフォントを割り振ることも可能ということです。ここでは日本語の2バイト文字とそれ以外で二種類のフォントを設定します。
- 適切に設定した
fontset
をdefault-frame-alist
に設定する。
default-frame-alist
というのは、起動時に最初に開くものも含めた新規のフレームに初期値として使用される設定をリストしておく変数です。ここに fontset
を設定することで実際に有効になります。
- 日本語と英語の横幅をそろえるため
face-font-rescale-alist
で比を設定する。
同じフォントサイズで単純に利用すると日本語の2バイト文字が1バイト文字の二倍の幅になりませんので微調節します。ただこれは、全部日本語フォントを使用すればそもそも問題が起きないという解決法もあるようです ( Emacs のフォント設定を克服する )。
- 日本語と英語の横幅をそろえたままフレーム全体のフォントサイズを調節します。
設定
はじめに
UTF-8の設定をしていますがこのあたりは見よう見まねでやっているので、本当に必要なのかはあまり理解しておりません。
;;;
;;; Unicode use
;; http://d.hatena.ne.jp/syou6162/20080519/1211133695
(set-locale-environment "utf-8")
(setenv "LANG" "en_US.UTF-8")
;; (setenv "LANG" "ja_JP.UTF-8")
;; http://www.emacswiki.org/emacs/EmacsForMacOS#toc18
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
主なフォント設定
-
準備として
let*
の部分で変数を定義-
myfonts
という名前のfontset
を定義します。 -
my-default-font-size
でデフォルトのフォントサイズを14ポイントとします。 - 英語文字用にはMenloを指定。
- 日本語文字用にはHiragino Maru Gothic ProNを指定。
- 英語フォントにさらに太さ(weight)と傾き(slant)を標準に設定するという設定を追加。
- 実際に
my-font-set
というfontset
として定義。 - 下記
fontspec
と呼ばれるオブジェクトを定義します。
-
-
実際の文字とフォントの割付の指定
-
my-font-set
の日本語部分のフォントをmy-jp-fontspec
(ヒラギノ)に設定。二行目はいらないかも。 -
my-font-set
の日本語半角カナ部分のフォントをmy-jp-fontspec
(ヒラギノ)に設定。 -
my-font-set
のラテン文字部分のフォントをmy-ascii-fontspec
(Menlo)に設定。 -
my-font-set
のギリシア文字部分のフォントをmy-ascii-fontspec
(Menlo)に設定。
-
-
default-frame-alist
への設定-
(font . "fontset-myfonts")
というペアを追加します。
-
-
face-font-rescale-alist
の設定- Hiragino Maru Gothic ProNでは1.2倍を指定するとよいと経験的に知られているようです。
- 過去の資料では他のフォントもいろいろ指定していますが、ここではヒラギノしか使っていませんので不要です。
;;;
;;; macOS font settings
(when (and (eq system-type 'darwin)
(display-graphic-p))
;; Best one so far. Good rescaling, and working with Greek letters φ phi
;; http://d.hatena.ne.jp/setoryohei/20110117
;; Good overview of how to configure a multi-language environment
;; http://qiita.com/melito/items/238bdf72237290bc6e42
;; Overview of an alternative method
;; http://lioon.net/emacs-change-font-size-quickly
;; Detailed explanation with Japanese font-only config
;; http://extra-vision.blogspot.com/2016/07/emacs.html?m=1
;; 37.12.11 Fontsets (Emacs Lisp Manual)
;; A fontset is a list of fonts, each assigned to a range of character codes.
;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Fontsets.html#Fontsets
;;
;; Strategy
;; 1. Create a fontset specifying Latin and Japanese letter separately
;; 2. Set default-frame fontset via default-frame-alist
;; 3. Set face-font-rescale-alist to match width of different fonts
;;
;;; Step 1. Create a fontset specifying different fonts for Latin and Japanese letters
;; This creates a new fontset rather than overwriting the default fontset.
(let* ((my-fontset-name "myfonts")
;; Font size one of [9/10/12/14/15/17/19/20/...]
(my-default-font-size 14)
;;
;; Ascii font name (pick from (font-family-list))
(my-ascii-font "Menlo")
;; Japanese font name (pick from (font-family-list))
(my-jp-font "Hiragino Maru Gothic ProN")
;;
;; Create a FONT string for create-fontset-from-ascii-font
;; "Menlo-14:weight=normal:slant=normal"
(my-default-font-string (format "%s-%d:weight=normal:slant=normal" my-ascii-font my-default-font-size))
;;
;; Create a fontset from an ASCII font FONT.
;; Name as "fontset-" added to my-fontset-name
;; "-*-menlo-normal-normal-normal-*-*-140-*-*-m-0-fontset-myfonts"
(my-font-set (create-fontset-from-ascii-font my-default-font-string nil my-fontset-name))
;;
;; Create :family-only font specifications (use later)
;; #<font-spec nil nil Menlo nil nil nil nil nil nil nil nil nil nil>
(my-ascii-fontspec (font-spec :family my-ascii-font))
;; #<font-spec nil nil Hiragino\ Maru\ Gothic\ ProN nil nil nil nil nil nil nil nil nil nil>
(my-jp-fontspec (font-spec :family my-jp-font)))
;;
;; set-fontset-font function
;; Modify fontset NAME to use FONT-SPEC for TARGET characters.
;; (set-fontset-font NAME TARGET FONT-SPEC &optional FRAME ADD)
;; NAME is a fontset name string, nil for the fontset of FRAME, or t for the default fontset.
;; TARGET may be a cons (FROM . TO) or a charset or others.
;; To list all possible choices, use M-x list-character-sets
;; FONT-SPEC may one of these:
;; * A font-spec object made by the function ‘font-spec’ (which see).
;; * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and
;; REGISTRY is a font registry name. FAMILY may contain foundry
;; name, and REGISTRY may contain encoding name.
;; * A font name string.
;; * nil, which explicitly specifies that there’s no font for TARGET.
;; FRAME is a frame or nil for the selected frame
;; ADD, if non-nil, specifies how to add FONT-SPEC to the font specifications for TARGET previously set
;; Use 'append if specifying overlapping
;;
;; For these Japanese character sets, use my-jp-fontspec
(set-fontset-font my-font-set 'japanese-jisx0213.2004-1 my-jp-fontspec nil 'append)
(set-fontset-font my-font-set 'japanese-jisx0213-2 my-jp-fontspec nil 'append)
;; For Half-sized katakana characters, use my-jp-fontspec
(set-fontset-font my-font-set 'katakana-jisx0201 my-jp-fontspec nil 'append)
;;
;; For the characters in the range #x0080 - #x024F, use my-ascii-fontspec
;; Latin with pronounciation annotations
(set-fontset-font my-font-set '(#x0080 . #x024F) my-ascii-fontspec nil 'append)
;; For the characters in the range #x0370 - #x03FF, use my-ascii-fontspec
;; Greek characters
(set-fontset-font my-font-set '(#x0370 . #x03FF) my-ascii-fontspec nil 'append))
;;
;;; Step 2. Set default-frame fontset via default-frame-alist
;; Set the font set for the default frame (Used at frame creation)
;; Alist of default values for frame creation.
;; To check for the current frame, use M-x describe-fontset
;; To examine a specific character under cursor, use M-x describe-font
(add-to-list 'default-frame-alist '(font . "fontset-myfonts"))
;;
;;; Step 3. Set face-font-rescale-alist to match width of different fonts
;; Rescaling parameters to adjust font sizes to match each other
(dolist (elt '(("Hiragino Maru Gothic ProN" . 1.2)
;; Below not relevant, but kept for historical reasons
;; ("^-apple-hiragino.*" . 1.2)
;; (".*osaka-bold.*" . 1.2)
;; (".*osaka-medium.*" . 1.2)
;; (".*courier-bold-.*-mac-roman" . 1.0)
;; (".*monaco cy-bold-.*-mac-cyrillic" . 0.9)
;; (".*monaco-bold-.*-mac-roman" . 0.9)
))
;; Alist of fonts vs the rescaling factors.
;; Each element is a cons (FONT-PATTERN . RESCALE-RATIO)
(add-to-list 'face-font-rescale-alist elt)))
さてここまで設定すると下記の文字の横幅がそろうはずです。
|012345 678910|
|abcdef ghijkl|
|ABCDEF GHIJKL|
|αβγδεζ ηθικλμ|
|ΑΒΓΔΕΖ ΗΘΙΚΛΜ|
|∩∪∞≤≥∏ ∑∫×±⊆⊇|
|'";:-+ =/\~`?|
|日本語 の美観|
|あいう えおか|
|アイウ エオカ|
|アイウエオカ キクケコサシ|
バッファごとに文字サイズを変更
これは M-x text-scale-adjust
で行うことができます。モードラインに対してバッファの文字が大きくなるのがわかるかと思います。日本語文字と英語文字の比を指定しているので、幅もそろったままです。
フレームごと文字サイズを変更
プロジェクタに写してライブデモをしたいときは、一つのバッファだけではなく、フレームのすべてのバッファの文字サイズを大きくしたいと思います。この一番簡単な方法は (set-face-attribute 'default nil :height (* 48 10))
を評価して標準のフォントサイズ(ポイントサイズの10倍を指定)を書き換えてしまう方法だと思います。ただこれはさきほど丁寧に設定した fontset
の設定を破壊してしまいます。前後で、 M-x describe-fontset
すると変化がわかります。下記ではモードラインも含めて文字が大きくなった(タイトルバーと比較)ものの、フォントが変化してバランスがくずれたのがわかるかと思います。
そこで、 fontset
が破壊されるならば再設定すればよいじゃないかということで、 update-current-frame-fontset
を定義しました。これは前述の設定からフォントサイズだけ除いたものを関数として定義しただけです。これを標準のフォントサイズを変更したあとに適用する default-font-size
というコマンドを定義しましました。これで M-x default-font-size RET 50 RET
でフォントサイズを50ポイントに変更して日本語フォントの再設定も同時におこないます。実は、48ポイントだと少しずれてしまいました、フォントサイズのきりが悪いと1.2倍の比がうまくいかないのだと思っていますが不明です。
関数の定義は下記のとおりです。macOS以外の環境でもやりたかったのですが、力つきました。もっと良い方法をご存知のかたは教えていただけると幸いです。
;;;
;;; Default font size setter (effective in all buffers)
;; http://stackoverflow.com/questions/294664/how-to-set-the-font-size-in-emacs
;; http://ergoemacs.org/emacs/elisp_idioms_prompting_input.html
;; current frame fontset updater for each OS
(defun update-current-frame-fontset-mac ()
"Update current frame fontset with Japanese font setting (macOS)"
(let* (;; Ascii font name (pick from (font-family-list))
(my-ascii-font "Menlo")
;; Japanese font name (pick from (font-family-list))
(my-jp-font "Hiragino Maru Gothic ProN")
;; Create :family-only font specifications (use later)
;; #<font-spec nil nil Menlo nil nil nil nil nil nil nil nil nil nil>
(my-ascii-fontspec (font-spec :family my-ascii-font))
;; #<font-spec nil nil Hiragino\ Maru\ Gothic\ ProN nil nil nil nil nil nil nil nil nil nil>
(my-jp-fontspec (font-spec :family my-jp-font)))
;;
;; Return the value of FACE’s ATTRIBUTE on (current) FRAME.
;; (face-attribute 'default :fontset) returns the current frame's fontset,
;; which can be updated for some letters via set-fontset-font
;; For these Japanese character sets, use my-jp-fontspec
(set-fontset-font (face-attribute 'default :fontset)
'japanese-jisx0213.2004-1 my-jp-fontspec nil 'append)
(set-fontset-font (face-attribute 'default :fontset)
'japanese-jisx0213-2 my-jp-fontspec nil 'append)
;; For Half-sized katakana characters, use my-jp-fontspec
(set-fontset-font (face-attribute 'default :fontset)
'katakana-jisx0201 my-jp-fontspec nil 'append)
;;
;; For the characters in the range #x0080 - #x024F, use my-ascii-fontspec
;; Latin with pronounciation annotations
(set-fontset-font (face-attribute 'default :fontset)
'(#x0080 . #x024F) my-ascii-fontspec nil 'append)
;; For the characters in the range #x0370 - #x03FF, use my-ascii-fontspec
;; Greek characters
(set-fontset-font (face-attribute 'default :fontset)
'(#x0370 . #x03FF) my-ascii-fontspec nil 'append)))
;;
(defun update-current-frame-fontset-win ()
"Update current frame fontset with Japanese font setting (Windows)"
nil)
;;
(defun update-current-frame-fontset-linux ()
"Update current frame fontset with Japanese font setting (Linux)"
nil)
;;
(defun update-current-frame-fontset ()
(cond
;; If in terminal, exit
((not (display-graphic-p)) nil)
;; Otherwise use appropriate one for each system
((eq system-type 'darwin) (update-current-frame-fontset-mac))
((eq system-type 'windows-nt) (update-current-frame-fontset-win))
((eq system-type 'gnu/linux) (update-current-frame-fontset-linux))
(t nil)))
;;
(defun default-font-size (size)
"Set default font size in current frame (effective in all buffers)"
(interactive "sEnter font size in points: ")
(let ((ht (* (string-to-int size) 10)))
(set-face-attribute 'default nil :height ht)
;; Call fontset updater to reinstall Japanese setting
(update-current-frame-fontset)))
備考
この文章の作成にはorg-modeからQiita形式のMarkdownを出力する ox-qmd を使用しました。日本語の入力には ddskk と google-ime-skk を利用しました。設定は 「Emacsのddskkで辞書をGoogle IMEにする」 を参考にしました。