如何为不同 face 设置不同的中文字体

rt,我尝试如下设置,但是注释里面的中文依旧是 Sarasa :

(dolist (charset '(kana han cjk-misc bopomofo))
  (set-fontset-font (frame-parameter nil 'font) charset
           (font-spec :family "Sarasa Mono SC Nerd")))
(set-face-attribute 'font-lock-comment-face nil :font "LXGW WenKai")

image

但是 face 又是对的

1 个赞

这个问题我也折腾了很久,目前我的理解是这样的:

  1. set-fontset-font 具有比 set-face-attribute 更高的优先级。
  2. 如果某个字符没有被 set-fontset-font 设置,且对应 face 中的 font 包括该字符,那么可以很好地显示该字符;但是如果这个 face 中的 font 不包括这个字符,那么 emacs 就会自己 fallback 一种字体来显示它(很随机,我也没搞懂怎么 fallback 的)。
  3. 如果某个字符已经被 set-fontset-font 设置,且这个 fontset 的 font 也能显示该字符,那么将无视这个字符的 face,直接使用 fontset 规定的字符;如果这个 fontset 的 font 不能显示该字符,则进入 emacs 的 字体 fallback。

我第一次发现这个问题,是在我使用 variable-pitch-modewriteroom-mode 的时候,发现对我通过 set-fontset-font 设置过的字体无效,原因就在于这个 mode 是通过设置 face 实现的,而其优先级比 fontset 低。

比如你可以做如下尝试,取消掉 fontset 的设置;

(dolist (charset '(kana han cjk-misc bopomofo))
  (set-fontset-font (frame-parameter nil 'font) charset
           (font-spec :family nil)))

然后就会发现通过 set-face-attribute 设置的部分生效了。

当然我目前的理解也可能有不正确的地方,给你提供几个我认为比较有价值的链接,尤其是第一个,更专业解释了我说的优先级问题。

What’s the relation between set-fontset-font and set-face-attribute?

Emacs, fonts and fontsets

Using Fontsets in Emacs

set-fontset-font vs. set-frame-font, what’s the difference?

How can I apply a user-defined fontset to a face?

这个我是知道的,但 set-fontset-font 只是设置某一个 fontset 里的字体,不会影响其他 fontset, 我尝试过用 create-fontset-from-fontset-spec 创建一个新的 fontset ,然后再 (set-face-attribute 'xxx-face nil :font "my fontset") ,但还是无效果

破案了,set-face-attritube 还需要设置 :fontset 才行,不然只是使用的字体集里面的 ascii 字体,剩余的字体还是从默认的 fontset 里找 #49797 - 28.0.50; Setting face to custom fontset doesn't work - GNU bug report logs

未设置:

已设置:

doc 里面说的不够准确,我以为把 fontset 传给 :font 就行了:

image

2 个赞

这个问题的起因是当 mode-line 里有中文的时候高度会变化,我想固定它的高度,我能找到的可用方案是

和 doom-modeline 里的方案,但是这两个方案都是取 mode-line 里字符高度的最大值,我觉得这样做会使我的 mode-line 变丑,所以考虑能否在 mode-line 里使用等高的中文字体。

下面是我的 mode-line face 设置,不知道是否有更优雅的实现:

(create-fontset-from-fontset-spec
	 (font-xlfd-name
	  (font-spec :family "InconsolataGo QiHei NF"
				 :registry "fontset-modeline fontset")))

	(dolist (charset '(kana han cjk-misc bopomofo unicode))
      (set-fontset-font "fontset-modeline fontset"  charset
			            (font-spec :family "InconsolataGo QiHei NF")))
	(set-fontset-font "fontset-modeline fontset" 'ascii
			          (font-spec :family "Cascadia Mono"))
	
	(dolist (face '(mode-line mode-line-inactive mode-line-buffer-id
							  mode-line-highlight mode-line-active
							  mode-line-emphasis))
	  (set-face-attribute face nil :fontset "fontset-modeline fontset"))
	(dolist (sym '(?● ?■ ?◢))
	  (set-fontset-font "fontset-modeline fontset" sym
						(font-spec :family "Sarasa Mono SC Nerd" :size 12)))
1 个赞

感谢!非常有用!

我发现非 ascii 字符(如中文字符)如预期那样工作,但是 ascii 字符似乎按照如下设置没用:

而是需要在 set-face-attribute 里面指定,才能生效:

(set-face-attribute face nil :fontset "fontset-modeline fontset" :family "Cascadia Mono")

请问你有这个问题吗?