分享:为不同的 org-mode 格式设置不同的中文字体

先上效果图:

image

我喜欢用 serif 作为正文字体,相对应地,我一般用宋体作为中文正文字体。另一方面,单个中文字体很多时候并不存在 italic / verbatim 一类的变种,这种风格往往通过使用不同的字体实现。比如,使用楷体代替 italic,使用黑体代替 verbatim。

设置如下:

这个函数用来创建字体集(fontset):

(defun create-variable-pitch-fontset (name ascii-font han-font)
  "Create fontset named NAME with given ASCII-FONT and HAN-FONT."
  (let ((registry (concat "fontset-variable pitch " name)))
    (create-fontset-from-fontset-spec
     (font-xlfd-name
      (font-spec :family ascii-font
                 :registry registry)))
    (set-fontset-font registry 'han
                      (font-spec :family han-font))
    (set-fontset-font registry 'cjk-misc
                      (font-spec :family han-font))))

下面的代码创建了几个字体集(可以换成你喜欢的字体):

(create-variable-pitch-fontset "regular"
                               "BlexSerif Nerd Font"
                               "思源宋体")
(create-variable-pitch-fontset "italic"
                               "BlexSerif Nerd Font"
                               "霞鹜文楷")
(create-variable-pitch-fontset "verbatim"
                               "CaskaydiaCove NFM"
                               "思源黑体")

接下来设置 variable-pitch 的字体:

(set-face-attribute 'variable-pitch nil
                                    :family font
                                    :fontset "fontset-variable pitch regular")

最后设置 org-emphasis-alist

(defface org-emphasis-italic
  '((default :inherit italic))
  "My italic emphasis for Org.")

(set-face-attribute 'org-emphasis-italic nil :fontset "fontset-variable pitch italic")

(defface org-emphasis-verbatim
  '((default :inherit org-verbatim))
  "My verbatim emphasis for Org.")

(set-face-attribute 'org-emphasis-verbatim nil :fontset "fontset-variable pitch verbatim")

(defface org-emphasis-code
  '((default :inherit org-code))
  "My code emphasis for Org.")

(set-face-attribute 'org-emphasis-code nil :fontset "fontset-variable pitch verbatim")

(setq org-emphasis-alist
      '(("*" bold)
        ("/" org-emphasis-italic)
        ("_" underline)
        ("=" org-emphasis-verbatim org-verbatim verbatim)
        ("~" org-emphasis-code org-code verbatim)
        ("+" (:strike-through t))))

另外,如果你使用 mixed-pitch-mode,那么需要同时启用 variable-pitch-mode,因为前者只 remap 了 font family(不知道怎么翻译),而没有考虑 fontset(事实上在试验的过程中我发现 Emacs 在 remap 对于 fontset 的处理上好像有 bug)。

Emacs 关于字体集的设置有很多问题和没有写进文档的细节,关于此可以参照坛友 @casouri这篇文章,给了我很大帮助。

8 个赞

能不能单独为表格的英文设置字体么?

(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(org-table ((t (:background "#ebdbb2" :family "Sarasa Fixed SC")))))
(advice-add #'org-string-width :override #'org--string-width-1)

我是这样设置表格等宽的

1 个赞

英文字母的 italic verbatim 不算什么变种, 说白了就是换 样式/字体.
比如, 中文还是有 斜体 的, 不过好像确实没有 异宽中文字体?


为啥你图中的 斜体 二字不斜, 如果不是故意设置的话可能是你的字体缺对应的样式, 正常来讲是这样的

image

中文本来是没有斜体这个概念的,大多数中文字体的斜体只是把正体倾斜得出的效果,而这种效果往往很丑(

1 个赞

我之前也折腾过不同中文字体的问题,也是被文档坑了好久才发现

感谢分享,抄走了

正如楼上所说的,你图片中的中文斜体对应的西文概念或许是 slant,即直接将正文字体进行倾斜处理;italic 的概念更广泛,一些字体的 italic 等于 slant,另一些讲究一些或者说风格强烈一些的字体会单独设计一套 italic 样式。

以我个人的审美而言,汉字的 slant 很难看,但是很少会有中文字体附上一套对应 italic 的额外样式一起打包,所以我选择用不同的字体组合。有一些从外文翻译来的正规出版物也是这么做的,比如我记得小时候看的哈利波特里就用宋体作为正文字体,而楷体对应原文中的 italic 样式

3 个赞

这么说确实🤔楷体作为italic是挺不错的, 笔锋像手写, 就像英文的italic也是像手写一样. 另外我觉得英文的oblique也不协调, 并不是仅汉字这样

中间的 |----+------+----| 会异常,你那里有这种情况么?

没有异常,可能是你用的这个字体对连笔有处理?

和你一样的字体,有点奇怪。

我设置的字体是更纱等宽黑体,而你的截图里显示的字体似乎是文楷,应该有其他的字体设置覆盖了对表格单独的设置,又或是加载顺序的问题

英文字体是被更纱黑体覆盖了,中文字体没被覆盖,按理说错位的字符也是更纱黑体。

org-string-width is supposed to be more accurate compared to org--string-width-1. Do you have an example when org-string-width does not work correctly?


org--string-width-1相比,org-string-width应该更准确。当org-string-width无法正常工作时,您是否有示例?

ref: org 9.6.5 用更纱黑体后, org 表格中文对不齐? - #9,来自 ringawho

Thanks! Should be fixed on Org side: emacs/org-mode.git - Emacs Org mode

2 个赞

貌似会报错: Debugger entered–Lisp error: (void-function create-variable-pitch-fontset) (create-variable-pitch-fontset “regular” “BlexSerif Nerd Font” “思源宋体”) (let ((print-level nil) (print-length nil)) (create-variable-pitch-fontset “regular” “BlexSerif Nerd Font” “思源宋体”)) (setq elisp–eval-defun-result (let ((print-level nil) (print-length nil)) (create-variable-pitch-fontset “regular” “BlexSerif Nerd Font” “思源宋体”))) elisp–eval-defun() #(nil) edebug–eval-defun(# nil) apply(edebug–eval-defun # nil) eval-defun(nil) eros-eval-defun(nil) funcall-interactively(eros-eval-defun nil) command-execute(eros-eval-defun)